Polled data will be send to the poller, Added some settings

parent ca95cca7
Pipeline #350 passed with stage
in 1 minute and 12 seconds
## v2.1.0 - 2020-04-22
- Polled data will always be send to the address of the polling node
- Made *server address*, *own address* and *delay after send* configurable at runtime
## v2.0.0 - 2020-04-13
- Added support for DS18B20, DS18S20, DS1820, DS1822 temperature sensors
- Added polling mode
......
......@@ -90,6 +90,17 @@ class WateringClient {
} else {
document.getElementById('pushDataEnabled').disabled = true;
}
// server address can only be set in >= v2.1.0
if (checkVersionGe(this.softwareVersion, '2.1.0')) {
document.getElementById('serverAddress').disabled = false;
document.getElementById('nodeAddress').disabled = false;
document.getElementById('delayAfterSend').disabled = false;
} else {
document.getElementById('serverAddress').disabled = true;
document.getElementById('nodeAddress').disabled = true;
document.getElementById('delayAfterSend').disabled = true;
}
}
if (info.settings) {
......@@ -112,6 +123,15 @@ class WateringClient {
} else {
document.getElementById('pushDataEnabled').checked = true;
}
if (checkVersionGe(this.softwareVersion, '2.1.0')) {
document.getElementById('serverAddress').value = info.settings.serverAddress;
document.getElementById('nodeAddress').value = info.settings.nodeAddress;
document.getElementById('delayAfterSend').value = info.settings.delayAfterSend;
} else {
document.getElementById('serverAddress').value = '';
document.getElementById('nodeAddress').value = '';
document.getElementById('delayAfterSend').value = 10;
}
}
} else {
document.getElementById('settings').style.display = 'none';
......@@ -239,7 +259,10 @@ class WateringClient {
checkInterval: document.getElementById('checkInterval').value,
tempSensorInterval: document.getElementById('tempSensorInterval').value,
sendAdcValuesThroughRH: document.getElementById('sendAdcValuesThroughRH').checked,
pushDataEnabled: document.getElementById('pushDataEnabled').checked
pushDataEnabled: document.getElementById('pushDataEnabled').checked,
serverAddress: document.getElementById('serverAddress').value,
nodeAddress: document.getElementById('nodeAddress').value,
delayAfterSend: document.getElementById('delayAfterSend').value
}),
headers: {
'content-type': 'application/json'
......@@ -324,7 +347,7 @@ class WateringClient {
body: JSON.stringify({
port: document.getElementById('port').value,
baud: document.getElementById('baud').value,
addressServer: document.getElementById('addressServer').value,
addressThis: document.getElementById('addressThis').value,
addressClient: document.getElementById('addressClient').value
}),
headers: {
......
......@@ -38,7 +38,7 @@
<div class="row">
<div class="cell">Address of this node</div>
<div class="cell">
<input type="text" id="addressServer" placeholder="0x01 or 1" value="0x01" required />
<input type="text" id="addressThis" placeholder="0x01 or 1" value="0x01" required />
</div>
</div>
<div class="row">
......@@ -98,6 +98,19 @@
<div class="cell"><input type="number" id="wateringTime3" min="1" max="65535" required /></div>
</div>
<div class="row">&nbsp;</div>
<div class="row">
<div class="cell">Own address</div>
<div class="cell"><input type="text" id="nodeAddress" placeholder="0xDC or 220" required /></div>
</div>
<div class="row">
<div class="cell">Push data to address</div>
<div class="cell"><input type="text" id="serverAddress" placeholder="0x01 or 1" required /></div>
</div>
<div class="row">
<div class="cell">Delay after send</div>
<div class="cell"><input type="number" id="delayAfterSend" min="0" max="65535" required /></div>
<div class="cell">milliseconds</div>
</div>
<div class="row">
<div class="cell">Check interval</div>
<div class="cell"><input type="number" id="checkInterval" min="1" max="65535" required /></div>
......
......@@ -155,11 +155,11 @@ class Watering {
const port = req.body.port;
const baud = parseInt(req.body.baud, 10);
let addressServer;
if (req.body.addressServer.startsWith('0x')) {
addressServer = parseInt(req.body.addressServer, 16);
let addressThis;
if (req.body.addressThis.startsWith('0x')) {
addressThis = parseInt(req.body.addressThis, 16);
} else {
addressServer = parseInt(req.body.addressServer, 10);
addressThis = parseInt(req.body.addressThis, 10);
}
if (req.body.addressClient.startsWith('0x')) {
this.addressClient = parseInt(req.body.addressClient, 16);
......@@ -167,7 +167,7 @@ class Watering {
this.addressClient = parseInt(req.body.addressClient, 10);
}
if (port.length > 0 && baud > 0 && addressServer > 0 && addressServer < 255 && this.addressClient > 0 && this.addressClient < 255) {
if (port.length > 0 && baud > 0 && addressThis > 0 && addressThis < 255 && this.addressClient > 0 && this.addressClient < 255) {
res.status(200);
res.send('Ok');
} else {
......@@ -177,7 +177,7 @@ class Watering {
}
// init RadioHead
this.rhs = new RadioHeadSerial(port, baud, addressServer);
this.rhs = new RadioHeadSerial(port, baud, addressThis);
this.rhs.setRetries(5);
this.rhs.on('data', this.rhsReceived);
......@@ -281,7 +281,26 @@ class Watering {
this.settings.pushDataEnabled = req.body.pushDataEnabled;
}
let buf = Buffer.alloc(22);
if (semver.satisfies(this.softwareVersion, '>=2.1.0')) {
if (req.body.serverAddress.startsWith('0x')) {
this.settings.serverAddress = parseInt(req.body.serverAddress, 16);
} else {
this.settings.serverAddress = parseInt(req.body.serverAddress, 10);
}
if (req.body.nodeAddress.startsWith('0x')) {
this.settings.nodeAddress = parseInt(req.body.nodeAddress, 16);
} else {
this.settings.nodeAddress = parseInt(req.body.nodeAddress, 10);
}
this.settings.delayAfterSend = parseInt(req.body.delayAfterSend, 10);
}
let buf;
if (semver.satisfies(this.softwareVersion, '>=2.1.0')) {
buf = Buffer.alloc(26);
} else {
buf = Buffer.alloc(22);
}
buf[0] = RH_MSG_SET_SETTINGS;
let bools = 0;
......@@ -302,6 +321,12 @@ class Watering {
buf.writeUInt16LE(this.settings.checkInterval, 18);
buf.writeUInt16LE(this.settings.tempSensorInterval, 20);
if (semver.satisfies(this.softwareVersion, '>=2.1.0')) {
buf[22] = this.settings.serverAddress;
buf[23] = this.settings.nodeAddress;
buf.writeUInt16LE(this.settings.delayAfterSend, 24);
}
this.rhsSend(buf);
res.send('Ok');
......@@ -523,6 +548,11 @@ class Watering {
if (semver.satisfies(this.softwareVersion, '>=2.0.0')) {
this.settings.pushDataEnabled = ((msg.data[1] & (1 << 6)) != 0);
}
if (semver.satisfies(this.softwareVersion, '>=2.1.0')) {
this.settings.serverAddress = msg.data[22];
this.settings.nodeAddress = msg.data[23];
this.settings.delayAfterSend = msg.data.readUInt16LE(24);
}
break;
case RH_MSG_VERSION:
......
This diff is collapsed.
{
"name": "auto-watering-control",
"version": "2.0.0",
"version": "2.1.0",
"description": "Control tool for the automatic watering system",
"main": "index.js",
"scripts": {
......
......@@ -58,12 +58,13 @@
/*
* RadioHead
*/
// the own RadioHead address
// The default own RadioHead address. Can be overwritten by settings.
#define RH_OWN_ADDR 0xDC // 220
// the server RadioHead address
// The default server RadioHead address. Can be overwritten by settings.
#define RH_SERVER_ADDR 0x01
// RadioHead bitrate in bit/s
#define RH_SPEED 2000
......
......@@ -20,11 +20,11 @@
// version number of the software
#define SOFTWARE_VERSION_MAJOR 2
#define SOFTWARE_VERSION_MINOR 0
#define SOFTWARE_VERSION_MINOR 1
#define SOFTWARE_VERSION_PATCH 0
// version of the eeporm data model; must be increased if the data model changes
#define EEPROM_VERSION 2
#define EEPROM_VERSION 4
// eeprom addresses
#define EEPROM_ADDR_VERSION 0 // 1 byte
......@@ -45,6 +45,9 @@ struct Settings {
uint16_t tempSensorInterval; // temperature sensor read interval in seconds
bool sendAdcValuesThroughRH; // send all adc values through RadioHead or not
bool pushDataEnabled; // if data will be actively pushed by the system over RadioHead
uint8_t serverAddress; // the address of the server in the RadioHead network
uint8_t ownAddress; // the address of this node in the RadioHead network
uint16_t delayAfterSend; // time in milliseconds to delay after each data send
};
/**
......
......@@ -33,6 +33,7 @@ void rhInit () {
}
rhManager.setRetries(RH_SEND_RETRIES);
rhManager.setTimeout(RH_SEND_TIMEOUT);
rhManager.setThisAddress(settings.ownAddress); // apply own address from settings
}
/**
......@@ -72,15 +73,19 @@ void rhRecv () {
if (settings.pushDataEnabled) {
rhBufTx[1] |= (1 << 6);
}
memcpy(&rhBufTx[18], &settings.checkInterval, 2);
memcpy(&rhBufTx[20], &settings.tempSensorInterval, 2);
rhBufTx[22] = settings.serverAddress;
rhBufTx[23] = settings.ownAddress;
memcpy(&rhBufTx[24], &settings.delayAfterSend, 2);
rhSend(RH_MSG_SETTINGS, 22, RH_FORCE_SEND);
rhSend(RH_MSG_SETTINGS, 26, rhRxFrom);
break;
case RH_MSG_SET_SETTINGS:
// got new settings
if (rhRxLen < 22) {
if (rhRxLen < 26) {
return;
}
for (uint8_t chan = 0; chan < 4; chan++) {
......@@ -92,6 +97,15 @@ void rhRecv () {
settings.pushDataEnabled = ((rhBufRx[1] & (1 << 6)) != 0);
memcpy(&settings.checkInterval, &rhBufRx[18], 2);
memcpy(&settings.tempSensorInterval, &rhBufRx[20], 2);
settings.serverAddress = rhBufRx[22];
// apply changed own address
if (settings.ownAddress != rhBufRx[23]) {
settings.ownAddress = rhBufRx[23];
rhManager.setThisAddress(settings.ownAddress);
}
memcpy(&settings.delayAfterSend, &rhBufRx[24], 2);
// calc new read times
// temperature sensor read is 5 seconds before adc read to avoid both readings at the same time
......@@ -155,36 +169,36 @@ void rhRecv () {
// poll with data
switch (rhBufRx[1]) {
case RH_MSG_BATTERY:
rhSendData(RH_MSG_BATTERY, RH_FORCE_SEND);
rhSendData(RH_MSG_BATTERY, RH_FORCE_SEND, rhRxFrom);
break;
case RH_MSG_CHANNEL_STATE:
rhSendData(RH_MSG_CHANNEL_STATE, RH_FORCE_SEND);
rhSendData(RH_MSG_CHANNEL_STATE, RH_FORCE_SEND, rhRxFrom);
break;
case RH_MSG_TEMP_SENSOR_DATA:
rhSendData(RH_MSG_TEMP_SENSOR_DATA, RH_FORCE_SEND);
rhSendData(RH_MSG_TEMP_SENSOR_DATA, RH_FORCE_SEND, rhRxFrom);
break;
case RH_MSG_SENSOR_VALUES:
rhSendData(RH_MSG_SENSOR_VALUES, RH_FORCE_SEND);
rhSendData(RH_MSG_SENSOR_VALUES, RH_FORCE_SEND, rhRxFrom);
break;
default:
// no known poll request... send all
rhSendData(RH_MSG_BATTERY, RH_FORCE_SEND);
rhSendData(RH_MSG_CHANNEL_STATE, RH_FORCE_SEND);
rhSendData(RH_MSG_TEMP_SENSOR_DATA, RH_FORCE_SEND);
rhSendData(RH_MSG_SENSOR_VALUES, RH_FORCE_SEND);
rhSendData(RH_MSG_BATTERY, RH_FORCE_SEND, rhRxFrom);
rhSendData(RH_MSG_CHANNEL_STATE, RH_FORCE_SEND, rhRxFrom);
rhSendData(RH_MSG_TEMP_SENSOR_DATA, RH_FORCE_SEND, rhRxFrom);
rhSendData(RH_MSG_SENSOR_VALUES, RH_FORCE_SEND, rhRxFrom);
}
} else {
// poll without data... send all
rhSendData(RH_MSG_BATTERY, RH_FORCE_SEND);
rhSendData(RH_MSG_CHANNEL_STATE, RH_FORCE_SEND);
rhSendData(RH_MSG_TEMP_SENSOR_DATA, RH_FORCE_SEND);
rhSendData(RH_MSG_SENSOR_VALUES, RH_FORCE_SEND);
rhSendData(RH_MSG_BATTERY, RH_FORCE_SEND, rhRxFrom);
rhSendData(RH_MSG_CHANNEL_STATE, RH_FORCE_SEND, rhRxFrom);
rhSendData(RH_MSG_TEMP_SENSOR_DATA, RH_FORCE_SEND, rhRxFrom);
rhSendData(RH_MSG_SENSOR_VALUES, RH_FORCE_SEND, rhRxFrom);
}
break;
case RH_MSG_GET_VERSION:
// send the software version
rhSendData(RH_MSG_VERSION, RH_FORCE_SEND);
rhSendData(RH_MSG_VERSION, RH_FORCE_SEND, rhRxFrom);
break;
case RH_MSG_PING:
......@@ -192,7 +206,7 @@ void rhRecv () {
for (uint8_t i = 1; i < rhRxLen; i++) {
rhBufTx[i] = rhBufRx[i];
}
rhSend(RH_MSG_PONG, rhRxLen, RH_FORCE_SEND); // use rhSend directly to allow variable data length
rhSend(RH_MSG_PONG, rhRxLen, rhRxFrom); // use rhSend directly to allow variable data length
break;
}
}
......@@ -204,11 +218,12 @@ void rhRecv () {
* The data part of the message must be set in rhBufTx before calling this function.
* @param msgType Type-code of this message. Will be set in rhBufTx[0].
* @param len Length of the data including the type byte.
* @param sendTo Target address to send the message to. Defaults to the configured server address.
* @return `true` if the message is successfully send.
*/
bool rhSend(uint8_t msgType, uint8_t len, uint8_t delayAfterSend) {
bool rhSend(uint8_t msgType, uint8_t len, uint8_t sendTo, uint8_t delayAfterSend) {
rhBufTx[0] = msgType;
if (!rhManager.sendtoWait(rhBufTx, len, RH_SERVER_ADDR)) {
if (!rhManager.sendtoWait(rhBufTx, len, sendTo)) {
blinkCode(BLINK_CODE_RH_SEND_ERROR);
return false;
}
......@@ -223,9 +238,10 @@ bool rhSend(uint8_t msgType, uint8_t len, uint8_t delayAfterSend) {
* The data part and the length of the message will be automatically set by global variables.
* @param msgType Type-code of this message. Will be set in rhBufTx[0].
* @param forceSend Send the message event if push data is disabled. (default false)
* @param sendTo Target address to send the message to. Defaults to the configured server address.
* @return `true` if the message is successfully send.
*/
bool rhSendData(uint8_t msgType, bool forceSend, uint8_t delayAfterSend) {
bool rhSendData(uint8_t msgType, bool forceSend, uint8_t sendTo, uint8_t delayAfterSend) {
if (!forceSend && !settings.pushDataEnabled) {
// to nothing if push data is not enabled and we should not force sending data
return true;
......@@ -302,5 +318,5 @@ bool rhSendData(uint8_t msgType, bool forceSend, uint8_t delayAfterSend) {
}
// send the data
return rhSend(msgType, len, delayAfterSend);
return rhSend(msgType, len, sendTo, delayAfterSend);
}
......@@ -37,8 +37,8 @@
// buffer for RadioHead messages
// rhBuf?x[0] - message type
#define RH_BUF_TX_LEN 22
#define RH_BUF_RX_LEN 22
#define RH_BUF_TX_LEN 26
#define RH_BUF_RX_LEN 26
extern uint8_t rhBufTx[RH_BUF_TX_LEN];
extern uint8_t rhBufRx[RH_BUF_RX_LEN];
......@@ -50,7 +50,7 @@ extern uint8_t rhBufRx[RH_BUF_RX_LEN];
void rhInit ();
void rhRecv ();
bool rhSend(uint8_t msgType, uint8_t len, uint8_t delayAfterSend = 10);
bool rhSendData(uint8_t msgType, bool forceSend = RH_SEND_ONLY_WHEN_PUSH_ENABLED, uint8_t delayAfterSend = 10);
bool rhSend(uint8_t msgType, uint8_t len, uint8_t sendTo = settings.serverAddress, uint8_t delayAfterSend = settings.delayAfterSend);
bool rhSendData(uint8_t msgType, bool forceSend = RH_SEND_ONLY_WHEN_PUSH_ENABLED, uint8_t sendTo = settings.serverAddress, uint8_t delayAfterSend = settings.delayAfterSend);
#endif
......@@ -24,6 +24,9 @@ void loadDefaultSettings () {
settings.tempSensorInterval = 60; // temperature sensor read interval - 1 minute
settings.sendAdcValuesThroughRH = true; // send all read adc values using through RadioHead
settings.pushDataEnabled = true; // push data actively via RadioHead
settings.serverAddress = RH_SERVER_ADDR; // RadioHead remote node address
settings.ownAddress = RH_OWN_ADDR; // RadioHead address of this node
settings.delayAfterSend = 10; // milliseconds to delay after each send
}
/**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment