Skip to content

Commit f904956

Browse files
Merge pull request #25 from vzakharchenko/added_cron_configuration
added cron configuration page
2 parents a70c1d2 + 6cf7ac7 commit f904956

28 files changed

+219
-36
lines changed

.github/workflows/docker.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,5 @@ jobs:
3333
platforms: linux/amd64,linux/arm64,linux/ppc64le,linux/arm/v7
3434
push: true
3535
tags: |
36-
vassio/smartthings-phevctl:1.3.9
36+
vassio/smartthings-phevctl:1.3.10
3737
vassio/smartthings-phevctl:latest

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ RUN cd /opt/phevctl/phevcore && mkdir build && cd build && cmake .. && make && m
2222
RUN cd /opt/phevctl/phevctl && mkdir -p build && cd build && cmake .. && make
2323
RUN ln -sf /opt/phevctl/phevctl/build/phevctl /usr/bin/phevctl
2424
# Bundle APP files
25-
RUN npm i [email protected].9 -g
25+
RUN npm i [email protected].10 -g
2626
# Install app dependencies
2727
ENV NPM_CONFIG_LOGLEVEL warn
2828

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
# Smartthings and SMS Remote control for Outlander PHEV
2-
Smartthings application wrapper over phevctl
2+
SMS and Smartthings application wrapper over phevctl
33
- [![Node.js CI](https://github.com/vzakharchenko/smartthings-phevctl/actions/workflows/build.yml/badge.svg)](https://github.com/vzakharchenko/smartthings-phevctl/actions/workflows/build.yml)
44
- [![docker](https://github.com/vzakharchenko/smartthings-phevctl/actions/workflows/docker.yml/badge.svg)](https://github.com/vzakharchenko/smartthings-phevctl/actions/workflows/docker.yml)
5-
- [![docker-armv6](https://github.com/vzakharchenko/smartthings-phevctl/actions/workflows/docker_armv6.yml/badge.svg)](https://github.com/vzakharchenko/smartthings-phevctl/actions/workflows/docker_armv6.yml)
65
- [![NPM](https://nodei.co/npm/smartthings-phevctl.png)](https://npmjs.org/package/smartthings-phevctl)
76
- [![donate](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://secure.wayforpay.com/button/b7a954a7c7177)
87

lib/cronConnection.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const { CronJob } = require('cron');
2+
const { readConfig } = require('./env');
23
const { updateSmartthingsDevices } = require('./smartthingsConnection');
34
const { logger } = require('./logger');
45
const { syncSmartthingsDevices } = require('./smartthingsConnection');
@@ -11,11 +12,12 @@ async function updateDevices() {
1112
}
1213

1314
function installCrons() {
14-
const cronJob = new CronJob('0 */30 * * * *', (async () => {
15+
const rc = readConfig();
16+
const cronJob = new CronJob(rc.cron.syncDevices, (async () => {
1517
await syncDevices();
1618
}), null, true);
1719
logger.debug('System TZ next 5: ', cronJob.nextDates(5));
18-
const cronJob2 = new CronJob('0 */10 * * * *', (async () => {
20+
const cronJob2 = new CronJob(rc.cron.updateDevices, (async () => {
1921
await updateDevices();
2022
}), null, true);
2123
logger.debug('System TZ next 5: ', cronJob2.nextDates(5));

lib/env.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ const defaultSettings = {
1111
sendNotification: true,
1212
devices: [],
1313
},
14+
cron: {
15+
syncDevices: '0 */30 * * * *',
16+
updateDevices: '0 */10 * * * *',
17+
},
1418
smartapp: [
1519
'https://graph.api.smartthings.com',
1620
'https://graph-na02-useast1.api.smartthings.com',
@@ -59,6 +63,9 @@ function readConfig() {
5963
password: 'admin',
6064
};
6165
}
66+
if (!configJson.cron) {
67+
configJson.cron = defaultSettings.cron;
68+
}
6269
return configJson;
6370
}
6471

lib/settingManager.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
const { restartApplication } = require('./executeService');
12
const { smartthingsNotification } = require('./smartthingsConnection');
23
const { logger } = require('./logger');
34
const { executeActionDirect } = require('./executeService');
@@ -51,7 +52,19 @@ function saveSetting(req, res) {
5152
});
5253
curConfig.users = newUserList;
5354
}
55+
let cron = false;
56+
if (reqConfig.cron) {
57+
if (reqConfig.cron.updateDevices !== readConfigOrigin.cron.updateDevices) {
58+
cron = true;
59+
}
60+
if (reqConfig.cron.syncDevices !== readConfigOrigin.cron.syncDevices) {
61+
cron = true;
62+
}
63+
}
5464
saveConfig(curConfig);
65+
if (cron) {
66+
restartApplication().then();
67+
}
5568
res.end(JSON.stringify({ status: 'OK' }));
5669
}
5770

lib/smartthingsConnection.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,11 @@ async function syncSmartthingsDevices() {
118118
if (curConfig.smartthings.devices == null) {
119119
curConfig.smartthings.devices = [];
120120
}
121-
const { devices } = await smartthingsAllDevice();
121+
const allDevices = await smartthingsAllDevice();
122+
if (!allDevices) {
123+
return;
124+
}
125+
const { devices } = allDevices;
122126
// eslint-disable-next-line no-plusplus
123127
for (let i = 0; i < devices.length; i++) {
124128
const existingDevice = curConfig.smartthings.devices.find((d) => d.id === devices[i].id);
@@ -206,7 +210,6 @@ async function updateSmartthingsDevices() {
206210
if (curConfig.smartthings.devices == null) {
207211
curConfig.smartthings.devices = [];
208212
}
209-
const devices = curConfig.smartthings.devices.filter((device) => device.updatable);
210213
if (curConfig.smartthings.sendNotification
211214
|| curConfig.smartthings.sms.sendSMSNotification) {
212215
const message = await getNotificationByActionId('batteryWarning', curConfig);
@@ -221,6 +224,7 @@ async function updateSmartthingsDevices() {
221224
addSMSNotification2('errACinfo');
222225
}
223226
}
227+
const devices = curConfig.smartthings.devices.filter((device) => device.updatable);
224228
if (devices.length > 0) {
225229
if (curConfig.smartthings.executeUpdate) {
226230
await forceUpdate(curConfig);

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "smartthings-phevctl",
3-
"version": "1.3.9",
3+
"version": "1.3.10",
44
"description": "smartthings remote ctrl",
55
"main": "smartthings-phevctl.js",
66
"scripts": {

remote-ctrl-ui/src/components/Constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ export const CONTENTS = {
55
AddUser: 'ADD_USER',
66
ViewUser: 'VIEW_USER',
77
SMS: 'SMS',
8+
CRON: 'CRON',
89
};
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import * as React from 'react';
2+
import {
3+
Alert, Button, Table,
4+
} from 'antd';
5+
import Paragraph from 'antd/es/typography/Paragraph';
6+
import { getLabels, setLanguage } from '../utils/Localization';
7+
import { fetchBackend, sendToBackend } from '../utils/restCalls';
8+
9+
export class CronSettings extends React.Component {
10+
state = {
11+
settings: {},
12+
changed: false,
13+
error: '',
14+
updateDevices: '',
15+
syncDevices: '',
16+
loading: false,
17+
};
18+
19+
async componentDidMount() {
20+
await this.reload();
21+
}
22+
23+
async onSaveClick() {
24+
const {
25+
settings,
26+
updateDevices,
27+
syncDevices,
28+
} = this.state;
29+
this.setState({ loading: true });
30+
const copyConfig = JSON.parse(JSON.stringify(settings.data));
31+
if (updateDevices) {
32+
copyConfig.cron.updateDevices = updateDevices;
33+
}
34+
if (syncDevices) {
35+
copyConfig.cron.syncDevices = syncDevices;
36+
}
37+
try {
38+
const res = await sendToBackend('/ui/settings', 'POST', copyConfig);
39+
const status = JSON.parse(res.data);
40+
if (status.status === 'OK') {
41+
const event = { changed: false };
42+
await this.props.reload();
43+
await this.reload();
44+
this.setState(event);
45+
} else {
46+
this.setState({ error: status.message });
47+
}
48+
} finally {
49+
this.setState({ loading: false });
50+
}
51+
}
52+
53+
getColumns() {
54+
return [
55+
{
56+
title: 'Name',
57+
dataIndex: 'name',
58+
key: 'name',
59+
render: (text) => <a>{getLabels()[text] || text}</a>,
60+
},
61+
{
62+
title: 'Value',
63+
dataIndex: 'value',
64+
key: 'value',
65+
render: (text, data) => {
66+
const value = this.state[data.name];
67+
return (
68+
<Paragraph editable={{
69+
onChange: (newValue) => {
70+
if (newValue) {
71+
const newState = { changed: true };
72+
newState[data.name] = newValue;
73+
this.setState(newState);
74+
}
75+
},
76+
}}
77+
>
78+
{value}
79+
</Paragraph>
80+
);
81+
},
82+
},
83+
];
84+
}
85+
86+
async reload() {
87+
const { data } = await fetchBackend('/ui/settings');
88+
const settings = JSON.parse(data);
89+
setLanguage(settings.data.language || 'English');
90+
this.setState({
91+
settings,
92+
updateDevices: settings.data.cron.updateDevices,
93+
syncDevices: settings.data.cron.syncDevices,
94+
});
95+
}
96+
97+
render() {
98+
const {
99+
settings, changed, loading, error,
100+
} = this.state;
101+
if (settings.status === 'OK') {
102+
const data = [{
103+
name: 'updateDevices',
104+
value: settings.data.cron.updateDevices,
105+
},
106+
{
107+
name: 'syncDevices',
108+
value: settings.data.cron.syncDevices,
109+
}];
110+
return (
111+
<div>
112+
{error ? (
113+
<Alert
114+
message={error}
115+
showIcon
116+
type="error"
117+
closable
118+
/>
119+
) : null}
120+
<Table pagination={false} columns={this.getColumns()} dataSource={data} />
121+
<Button
122+
type="primary"
123+
loading={loading}
124+
block
125+
disabled={!changed}
126+
onClick={async () => {
127+
await this.onSaveClick();
128+
}}
129+
>
130+
{getLabels().save || 'Save'}
131+
</Button>
132+
</div>
133+
);
134+
}
135+
return null;
136+
}
137+
}

0 commit comments

Comments
 (0)