Compare commits
13 Commits
DropObsole
...
refactor_p
Author | SHA1 | Date | |
---|---|---|---|
b6077b0ec8 | |||
cab0aec533
|
|||
35c282b6ea | |||
4b860ee43a
|
|||
d3eae2cd8d
|
|||
768ded37a6
|
|||
2cadccf59c | |||
c779f07cda
|
|||
84f4ecf5a1 | |||
d8ce7c8bc2 | |||
080b22646d | |||
2a704738b2
|
|||
5c8b2599a6
|
2
ENV
2
ENV
@ -1,2 +0,0 @@
|
|||||||
export LD_LIBRARY_PATH=/home/pi/modbusmaster/pyserialext/
|
|
||||||
export PYTHONPATH=/home/pi/modbusmaster/pyserialext/
|
|
@ -1,14 +0,0 @@
|
|||||||
CFLAGS=
|
|
||||||
LIBS=-lwiringPi
|
|
||||||
|
|
||||||
writec.so: writec.o
|
|
||||||
$(LD) -shared $(LIBS) -o $@ $^
|
|
||||||
|
|
||||||
writec.o: writec.c
|
|
||||||
|
|
||||||
.c.o:
|
|
||||||
$(CC) $(CFLAGS) -c $<
|
|
||||||
|
|
||||||
.PHONY: clean
|
|
||||||
clean:
|
|
||||||
-rm -f *.so *.o
|
|
@ -1,16 +0,0 @@
|
|||||||
import serial.rs485
|
|
||||||
import serial.serialutil
|
|
||||||
import ctypes
|
|
||||||
|
|
||||||
|
|
||||||
class RS485Ext(serial.rs485.RS485):
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super(RS485Ext, self).__init__(*args, **kwargs)
|
|
||||||
self.writec = ctypes.cdll.LoadLibrary('writec.so')
|
|
||||||
r = self.writec.init()
|
|
||||||
|
|
||||||
def write(self, b):
|
|
||||||
d = serial.serialutil.to_bytes(b)
|
|
||||||
r = self.writec.writec(self.fileno(), d, len(d))
|
|
||||||
return r
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
|||||||
#include <unistd.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <wiringPi.h>
|
|
||||||
|
|
||||||
|
|
||||||
const uint8_t DE_PIN = 0;
|
|
||||||
|
|
||||||
int init() {
|
|
||||||
wiringPiSetup();
|
|
||||||
pinMode(DE_PIN, OUTPUT);
|
|
||||||
digitalWrite(DE_PIN, LOW);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t writec(int fd, char *buf, size_t count) {
|
|
||||||
digitalWrite(DE_PIN, HIGH);
|
|
||||||
ssize_t r = write(fd, buf, count);
|
|
||||||
uint8_t lsr;
|
|
||||||
do {
|
|
||||||
int r = ioctl(fd, TIOCSERGETLSR, &lsr);
|
|
||||||
} while (!(lsr & TIOCSER_TEMT));
|
|
||||||
digitalWrite(DE_PIN, LOW);
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
Submodule rpirtscts deleted from 612b065e38
@ -1,212 +0,0 @@
|
|||||||
-- Configuration and Provisioning Schema
|
|
||||||
|
|
||||||
|
|
||||||
DROP TABLE tReadDatapoint;
|
|
||||||
|
|
||||||
CREATE TABLE tReadDatapoint (
|
|
||||||
id INTEGER PRIMARY KEY AUTO_INCREMENT,
|
|
||||||
unit INTEGER NOT NULL,
|
|
||||||
address INTEGER NOT NULL,
|
|
||||||
count INTEGER NOT NULL,
|
|
||||||
converter VARCHAR(10) NOT NULL,
|
|
||||||
label VARCHAR(128) NOT NULL,
|
|
||||||
scanRate TIME(3) DEFAULT '00:00:01.000',
|
|
||||||
topic VARCHAR(256) NOT NULL,
|
|
||||||
lastContact TIMESTAMP(3) NOT NULL DEFAULT '2000-01-01 00:00:01.000',
|
|
||||||
lastError VARCHAR(512),
|
|
||||||
lastValue VARCHAR(512),
|
|
||||||
backoff TIME(3) DEFAULT '00:00:00.000',
|
|
||||||
available BOOLEAN DEFAULT TRUE,
|
|
||||||
retries INTEGER NOT NULL DEFAULT 0,
|
|
||||||
giveUpCount INTEGER NOT NULL DEFAULT 0,
|
|
||||||
active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
||||||
CONSTRAINT uniqueReadDatapoint UNIQUE (unit, address, count, label)
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO tReadDatapoint (unit, address, count, converter, label, topic, scanRate)
|
|
||||||
VALUES(4, 0x2000, 2, 'F', '(ERR) Unavailable device', 'IoT/ModbusMaster1/UnavailableDevice', '00:00:01.000');
|
|
||||||
INSERT INTO tReadDatapoint (unit, address, count, converter, label, topic, scanRate)
|
|
||||||
VALUES(1, 0x2000, 4, 'F', '(ERR) Wrong register size', 'IoT/ModbusMaster1/WrongRegisterSize', '00:05:00.000');
|
|
||||||
INSERT INTO tReadDatapoint (unit, address, count, converter, label, topic, scanRate)
|
|
||||||
VALUES(1, 0x2000, 2, 'F', 'Voltage', 'IoT/ModbusMaster1/Voltage', '00:05:00.000');
|
|
||||||
INSERT INTO tReadDatapoint (unit, address, count, converter, label, topic, scanRate)
|
|
||||||
VALUES(1, 0x2020, 2, 'F', 'Frequency', 'IoT/ModbusMaster1/Frequency', '00:05:00.000');
|
|
||||||
INSERT INTO tReadDatapoint (unit, address, count, converter, label, topic, scanRate)
|
|
||||||
VALUES(1, 0x2060, 2, 'F', 'Current', 'IoT/ModbusMaster1/Current', '00:05:00.000');
|
|
||||||
INSERT INTO tReadDatapoint (unit, address, count, converter, label, topic, scanRate)
|
|
||||||
VALUES(3, 0x0004, 2, 'RF', 'Resistance Channel 1', 'IoT/ModbusMaster1/Channel1/Resistance', '00:00:01.000');
|
|
||||||
INSERT INTO tReadDatapoint (unit, address, count, converter, label, topic, scanRate)
|
|
||||||
VALUES(3, 0x000C, 2, 'RF', 'Temperature Channel 1', 'IoT/ModbusMaster1/Channel1/Temperature', '00:00:01.000');
|
|
||||||
INSERT INTO tReadDatapoint (unit, address, count, converter, label, topic, scanRate)
|
|
||||||
VALUES(3, 0x0014, 2, 'RF', 'Resistance Channel 2', 'IoT/ModbusMaster1/Channel2/Resistance', '00:00:01.000');
|
|
||||||
INSERT INTO tReadDatapoint (unit, address, count, converter, label, topic, scanRate)
|
|
||||||
VALUES(3, 0x001C, 2, 'RF', 'Temperature Channel 2', 'IoT/ModbusMaster1/Channel2/Temperature', '00:00:01.000');
|
|
||||||
|
|
||||||
|
|
||||||
DROP TABLE tWriteDatapoint;
|
|
||||||
|
|
||||||
CREATE TABLE tWriteDatapoint (
|
|
||||||
id INTEGER PRIMARY KEY AUTO_INCREMENT,
|
|
||||||
unit INTEGER NOT NULL,
|
|
||||||
address INTEGER NOT NULL,
|
|
||||||
count INTEGER NOT NULL,
|
|
||||||
converter VARCHAR(10) NOT NULL,
|
|
||||||
label VARCHAR(128) NOT NULL,
|
|
||||||
topic VARCHAR(256) NOT NULL,
|
|
||||||
lastContact TIMESTAMP(3) NOT NULL DEFAULT '2000-01-01 00:00:01.000',
|
|
||||||
lastError VARCHAR(512),
|
|
||||||
value VARCHAR(512),
|
|
||||||
retries INTEGER NOT NULL DEFAULT 0,
|
|
||||||
active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
||||||
CONSTRAINT uniqueWriteDatapoint UNIQUE (unit, address, count, label)
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
INSERT INTO tWriteDatapoint (unit, address, count, converter, label, topic, active)
|
|
||||||
VALUES(5, 0x0000, 1, 'B', 'Relay 1', 'IoT/ModbusMaster1/Relay1', FALSE);
|
|
||||||
|
|
||||||
|
|
||||||
CREATE OR REPLACE VIEW vReadDatapointsToBeHandled AS
|
|
||||||
SELECT id, unit, address, count, converter
|
|
||||||
FROM tReadDatapoint
|
|
||||||
WHERE available AND
|
|
||||||
active AND
|
|
||||||
ADDTIME(lastContact, ADDTIME(scanRate, backoff)) < NOW(3)
|
|
||||||
ORDER BY scanRate;
|
|
||||||
|
|
||||||
CREATE OR REPLACE VIEW vWriteDatapintsToBeHandled AS
|
|
||||||
SELECT id, unit, address, count, converter, value
|
|
||||||
FROM tWriteDatapoint
|
|
||||||
WHERE active;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DROP TABLE tReadNotification;
|
|
||||||
|
|
||||||
CREATE TABLE tReadNotification (
|
|
||||||
id INTEGER PRIMARY KEY AUTO_INCREMENT,
|
|
||||||
readDatapointId INTEGER NOT NULL REFERENCES tReadDatapoint(id),
|
|
||||||
notificationType VARCHAR(1),
|
|
||||||
CONSTRAINT checkNotificationType CHECK (notificationtype IN ('V', 'F', 'R')) -- value, failure, return
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
DROP TABLE tWrittenNotification;
|
|
||||||
|
|
||||||
CREATE TABLE tWrittenNotification (
|
|
||||||
id INTEGER PRIMARY KEY AUTO_INCREMENT,
|
|
||||||
writeDatapointId INTEGER NOT NULL REFERENCES tWriteDatapoint(id),
|
|
||||||
notificationType VARCHAR(1),
|
|
||||||
CONSTRAINT checkNotificationType CHECK (notificationtype IN ('S', 'F')) -- success, failure
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DELIMITER $$
|
|
||||||
CREATE OR REPLACE PROCEDURE prWriteFeedback (IN p_id INTEGER, IN p_lastError VARCHAR(512))
|
|
||||||
MODIFIES SQL DATA
|
|
||||||
BEGIN
|
|
||||||
DECLARE v_retries INTEGER;
|
|
||||||
DECLARE v_active BOOLEAN;
|
|
||||||
|
|
||||||
IF p_lastError = '' OR p_lastError IS NULL THEN
|
|
||||||
UPDATE tWriteDatapoint
|
|
||||||
SET lastError = NULL,
|
|
||||||
lastContact = NOW(3),
|
|
||||||
retries = 0,
|
|
||||||
active = FALSE
|
|
||||||
WHERE id = p_id;
|
|
||||||
INSERT INTO tWrittenNotification (writeDatapointId, notificationType) VALUES (p_id, 'S');
|
|
||||||
ELSE
|
|
||||||
SELECT retries
|
|
||||||
INTO v_retries
|
|
||||||
FROM tWriteDatapoint
|
|
||||||
WHERE id = p_id;
|
|
||||||
|
|
||||||
SET v_retries := v_retries + 1;
|
|
||||||
|
|
||||||
IF v_retries >= 5 THEN
|
|
||||||
SET v_retries := 0;
|
|
||||||
SET v_active := FALSE;
|
|
||||||
ELSE
|
|
||||||
SET v_active := TRUE;
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
UPDATE tWriteDatapoint
|
|
||||||
SET lastError = p_lastError,
|
|
||||||
retries = v_retries,
|
|
||||||
active = v_active
|
|
||||||
WHERE id = p_id;
|
|
||||||
|
|
||||||
IF NOT v_active THEN
|
|
||||||
INSERT INTO tWrittenNotification (writeDatapointId, notificationType) VALUES(p_id, 'F');
|
|
||||||
END IF;
|
|
||||||
END IF;
|
|
||||||
END; $$
|
|
||||||
DELIMITER ;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DELIMITER $$
|
|
||||||
CREATE OR REPLACE PROCEDURE prReadFeedback (IN p_id INTEGER, IN p_lastValue VARCHAR(512), IN p_lastError VARCHAR(512))
|
|
||||||
MODIFIES SQL DATA
|
|
||||||
BEGIN
|
|
||||||
DECLARE v_retries INTEGER;
|
|
||||||
DECLARE v_backoff TIME(3);
|
|
||||||
DECLARE v_scanRate TIME(3);
|
|
||||||
DECLARE v_giveUpCount INTEGER;
|
|
||||||
DECLARE v_available BOOLEAN;
|
|
||||||
|
|
||||||
IF p_lastError = '' OR p_lastError IS NULL THEN
|
|
||||||
UPDATE tReadDatapoint
|
|
||||||
SET lastError = NULL,
|
|
||||||
lastContact = NOW(3),
|
|
||||||
lastValue = p_lastValue,
|
|
||||||
retries = 0,
|
|
||||||
backoff = '00:00:00.000',
|
|
||||||
giveUpCount = 0
|
|
||||||
WHERE id = p_id;
|
|
||||||
INSERT INTO tReadNotification (readDatapointId, notificationType) VALUES(p_id, 'V');
|
|
||||||
ELSE
|
|
||||||
SELECT retries, backoff, scanRate, giveUpCount
|
|
||||||
INTO v_retries, v_backoff, v_scanRate, v_giveUpCount
|
|
||||||
FROM tReadDatapoint
|
|
||||||
WHERE id = p_id;
|
|
||||||
|
|
||||||
SET v_retries := v_retries + 1;
|
|
||||||
|
|
||||||
IF v_retries >= 5 THEN
|
|
||||||
IF v_backoff = '00:00:00.000' THEN
|
|
||||||
SET v_backoff = v_scanRate;
|
|
||||||
ELSE
|
|
||||||
SET v_backoff = ADDTIME(v_backoff, v_backoff);
|
|
||||||
END IF;
|
|
||||||
SET v_retries := 0;
|
|
||||||
SET v_giveUpCount := v_giveUpCount + 1;
|
|
||||||
SET v_available := TRUE;
|
|
||||||
END IF;
|
|
||||||
IF v_giveUpCount = 10 THEN
|
|
||||||
SET v_available := FALSE;
|
|
||||||
SET v_giveUpCount := 0;
|
|
||||||
SET v_backoff := '00:00:00.000';
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
UPDATE tReadDatapoint
|
|
||||||
SET lastError = p_lastError,
|
|
||||||
retries = v_retries,
|
|
||||||
backoff = v_backoff,
|
|
||||||
giveUpCount = v_giveUpCount,
|
|
||||||
available = v_available
|
|
||||||
WHERE id = p_id;
|
|
||||||
|
|
||||||
IF NOT v_available THEN
|
|
||||||
INSERT INTO tReadNotification (readDatapointId, notificationType) VALUES(p_id, 'F');
|
|
||||||
END IF;
|
|
||||||
END IF;
|
|
||||||
END; $$
|
|
||||||
DELIMITER ;
|
|
||||||
|
|
||||||
|
|
@ -6,6 +6,7 @@ import io
|
|||||||
import datetime
|
import datetime
|
||||||
import RegisterDatapoint
|
import RegisterDatapoint
|
||||||
import logging
|
import logging
|
||||||
|
import Converters
|
||||||
|
|
||||||
class CmdInterpreterException(ValueError): pass
|
class CmdInterpreterException(ValueError): pass
|
||||||
|
|
||||||
@ -31,6 +32,14 @@ class CmdInterpreter(cmd.Cmd):
|
|||||||
self.splitterRe = re.compile('\s+')
|
self.splitterRe = re.compile('\s+')
|
||||||
self.logger = logging.getLogger('CmdInterpreter')
|
self.logger = logging.getLogger('CmdInterpreter')
|
||||||
|
|
||||||
|
def onecmd(self, line):
|
||||||
|
try:
|
||||||
|
return super().onecmd(line)
|
||||||
|
except Exception as e:
|
||||||
|
msg = 'Caught exception in cmd "{0}": {1!s}'.format(line, e)
|
||||||
|
self.__println(msg)
|
||||||
|
self.logger.error(msg)
|
||||||
|
|
||||||
def __print(self, text):
|
def __print(self, text):
|
||||||
self.stdout.write(text)
|
self.stdout.write(text)
|
||||||
|
|
||||||
@ -38,16 +47,10 @@ class CmdInterpreter(cmd.Cmd):
|
|||||||
self.stdout.write(text)
|
self.stdout.write(text)
|
||||||
self.stdout.write("\n\r")
|
self.stdout.write("\n\r")
|
||||||
|
|
||||||
def do_notify(self, arg):
|
|
||||||
self.notifier.notify()
|
|
||||||
|
|
||||||
def help_notify(self):
|
|
||||||
self.__println("Notifies threads using the list of datapoints about changes in this list.")
|
|
||||||
self.__println("Call after modifications on the list.")
|
|
||||||
|
|
||||||
def do_quit(self, arg):
|
def __listConverterNames(self):
|
||||||
self.__println("Bye!")
|
return [ name for name in Converters.Converters ]
|
||||||
return True
|
|
||||||
|
|
||||||
def do_add_hr(self, arg):
|
def do_add_hr(self, arg):
|
||||||
try:
|
try:
|
||||||
@ -74,7 +77,15 @@ class CmdInterpreter(cmd.Cmd):
|
|||||||
address = parseIntArbitraryBase(address)
|
address = parseIntArbitraryBase(address)
|
||||||
count = parseIntArbitraryBase(count)
|
count = parseIntArbitraryBase(count)
|
||||||
scanrate = float(scanrate)
|
scanrate = float(scanrate)
|
||||||
r = RegisterDatapoint.HoldingRegisterDatapoint(label, unit, address, count, datetime.timedelta(seconds=scanrate), readTopic, writeTopic, feedbackTopic, converter)
|
r = RegisterDatapoint.HoldingRegisterDatapoint(label=label,
|
||||||
|
unit=unit,
|
||||||
|
address=address,
|
||||||
|
count=count,
|
||||||
|
scanRate=datetime.timedelta(seconds=scanrate),
|
||||||
|
publishTopic=readTopic,
|
||||||
|
subscribe=writeTopic,
|
||||||
|
feedbackTopic=feedbackTopic,
|
||||||
|
converter=converter)
|
||||||
self.registers.append(r)
|
self.registers.append(r)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
self.__println("ERROR: {0!s}, {1!s}".format(e.__class__.__name__, e))
|
self.__println("ERROR: {0!s}, {1!s}".format(e.__class__.__name__, e))
|
||||||
@ -97,7 +108,7 @@ class CmdInterpreter(cmd.Cmd):
|
|||||||
self.__println("<WriteTopic> Topic to be subscribe to receive data to be")
|
self.__println("<WriteTopic> Topic to be subscribe to receive data to be")
|
||||||
self.__println(" written")
|
self.__println(" written")
|
||||||
self.__println("<FeedbackTopic> Topic to publish feedback after a write process,")
|
self.__println("<FeedbackTopic> Topic to publish feedback after a write process,")
|
||||||
self.__println("<Converter> Converter for data")
|
self.__println("<Converter> Converter for data, one of {0}".format(', '.join(self.__listConverterNames())))
|
||||||
|
|
||||||
|
|
||||||
def do_add_coil(self, arg):
|
def do_add_coil(self, arg):
|
||||||
@ -120,7 +131,13 @@ class CmdInterpreter(cmd.Cmd):
|
|||||||
unit = parseIntArbitraryBase(unit)
|
unit = parseIntArbitraryBase(unit)
|
||||||
address = parseIntArbitraryBase(address)
|
address = parseIntArbitraryBase(address)
|
||||||
scanrate = float(scanrate)
|
scanrate = float(scanrate)
|
||||||
r = RegisterDatapoint.CoilDatapoint(label, unit, address, datetime.timedelta(seconds=scanrate), readTopic, writeTopic, feedbackTopic)
|
r = RegisterDatapoint.CoilDatapoint(label=label,
|
||||||
|
unit=unit,
|
||||||
|
address=address,
|
||||||
|
scanRate=datetime.timedelta(seconds=scanrate),
|
||||||
|
publishTopic=readTopic,
|
||||||
|
subscribeTopic=writeTopic,
|
||||||
|
feedbackTopic=feedbackTopic)
|
||||||
self.registers.append(r)
|
self.registers.append(r)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
self.__println("ERROR: {0!s}, {1!s}".format(e.__class__.__name__, e))
|
self.__println("ERROR: {0!s}, {1!s}".format(e.__class__.__name__, e))
|
||||||
@ -167,7 +184,13 @@ class CmdInterpreter(cmd.Cmd):
|
|||||||
address = parseIntArbitraryBase(address)
|
address = parseIntArbitraryBase(address)
|
||||||
count = parseIntArbitraryBase(count)
|
count = parseIntArbitraryBase(count)
|
||||||
scanrate = float(scanrate)
|
scanrate = float(scanrate)
|
||||||
r = RegisterDatapoint.InputRegisterDatapoint(label, unit, address, count, datetime.timedelta(seconds=scanrate), updateOnly, readTopic, converter)
|
r = RegisterDatapoint.InputRegisterDatapoint(label=label,
|
||||||
|
unit=unit,
|
||||||
|
address=address,
|
||||||
|
count=count, scanRate=datetime.timedelta(seconds=scanrate),
|
||||||
|
updateOnly=updateOnly,
|
||||||
|
publishTopic=readTopic,
|
||||||
|
converter=converter)
|
||||||
self.registers.append(r)
|
self.registers.append(r)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
self.__println("ERROR: {0!s}, {1!s}".format(e.__class__.__name__, e))
|
self.__println("ERROR: {0!s}, {1!s}".format(e.__class__.__name__, e))
|
||||||
@ -185,7 +208,7 @@ class CmdInterpreter(cmd.Cmd):
|
|||||||
self.__println("<ScanRate> Scanrate in seconds (float)")
|
self.__println("<ScanRate> Scanrate in seconds (float)")
|
||||||
self.__println("<UpdateOnly> Publish only when value has changed")
|
self.__println("<UpdateOnly> Publish only when value has changed")
|
||||||
self.__println("<ReadTopic> Topic to publish read data")
|
self.__println("<ReadTopic> Topic to publish read data")
|
||||||
self.__println("<Converter> Converter for data")
|
self.__println("<Converter> Converter for data, one of {0}".format(', '.join(self.__listConverterNames())))
|
||||||
|
|
||||||
def do_add_di(self, arg):
|
def do_add_di(self, arg):
|
||||||
try:
|
try:
|
||||||
@ -212,7 +235,14 @@ class CmdInterpreter(cmd.Cmd):
|
|||||||
count = parseIntArbitraryBase(count)
|
count = parseIntArbitraryBase(count)
|
||||||
scanrate = float(scanrate)
|
scanrate = float(scanrate)
|
||||||
bitCount = int(bitCount)
|
bitCount = int(bitCount)
|
||||||
r = RegisterDatapoint.DiscreteInputDatapoint(label, unit, address, count, datetime.timedelta(seconds=scanrate), updateOnly, readTopic, None, bitCount)
|
r = RegisterDatapoint.DiscreteInputDatapoint(label=label,
|
||||||
|
unit=unit,
|
||||||
|
address=address,
|
||||||
|
count=count,
|
||||||
|
scanRate=datetime.timedelta(seconds=scanrate),
|
||||||
|
updateOnly=updateOnly,
|
||||||
|
publishTopic=readTopic,
|
||||||
|
bitCount=bitCount)
|
||||||
self.registers.append(r)
|
self.registers.append(r)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
self.__println("ERROR: {0!s}, {1!s}".format(e.__class__.__name__, e))
|
self.__println("ERROR: {0!s}, {1!s}".format(e.__class__.__name__, e))
|
||||||
@ -244,7 +274,8 @@ class CmdInterpreter(cmd.Cmd):
|
|||||||
def do_reset(self, arg):
|
def do_reset(self, arg):
|
||||||
for r in self.registers:
|
for r in self.registers:
|
||||||
r.errorCount = 0
|
r.errorCount = 0
|
||||||
r.processCount = 0
|
r.writeCount = 0
|
||||||
|
r.readCount = 0
|
||||||
|
|
||||||
def help_reset(self):
|
def help_reset(self):
|
||||||
self.__println("Usage: reset")
|
self.__println("Usage: reset")
|
||||||
@ -253,13 +284,13 @@ class CmdInterpreter(cmd.Cmd):
|
|||||||
|
|
||||||
def do_stats(self, arg):
|
def do_stats(self, arg):
|
||||||
for i, r in enumerate(self.registers):
|
for i, r in enumerate(self.registers):
|
||||||
processCount = readCount + writeCount
|
processCount = r.readCount + r.writeCount
|
||||||
if processCount == 0:
|
if processCount == 0:
|
||||||
ratio = -1
|
ratio = -1
|
||||||
else:
|
else:
|
||||||
ratio = float(r.errorCount) / float(processCount)
|
ratio = float(r.errorCount) / float(processCount)
|
||||||
self.__println("#{0:2d}: {1:15s} ({2:2d}, {3:5d}), rc: {4:7d}, wc: {4:7d}, pc: {4:7d}, ec: {5:7d}, q: {6:1.4f}"
|
self.__println("#{0:2d}: {1:15s} ({2:2d}, {3:5d}), rc: {4:7d}, wc: {5:7d}, pc: {6:7d}, ec: {7:7d}, q: {8:1.4f}"
|
||||||
.format(i, r.label, r.unit, r.address, r.readCount, r.writeCount
|
.format(i, r.label, r.unit, r.address, r.readCount, r.writeCount,
|
||||||
processCount, r.errorCount, ratio))
|
processCount, r.errorCount, ratio))
|
||||||
|
|
||||||
def help_stats(self):
|
def help_stats(self):
|
||||||
@ -267,8 +298,6 @@ class CmdInterpreter(cmd.Cmd):
|
|||||||
self.__println("-----------")
|
self.__println("-----------")
|
||||||
self.__println("List the statistics of configured datapoints")
|
self.__println("List the statistics of configured datapoints")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def do_change(self, arg):
|
def do_change(self, arg):
|
||||||
(idx, key, typ, value) = self.splitterRe.split(arg)
|
(idx, key, typ, value) = self.splitterRe.split(arg)
|
||||||
try:
|
try:
|
||||||
@ -320,9 +349,6 @@ class CmdInterpreter(cmd.Cmd):
|
|||||||
self.__println(" considered)")
|
self.__println(" considered)")
|
||||||
self.__println("<value> New value")
|
self.__println("<value> New value")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def do_del(self, arg):
|
def do_del(self, arg):
|
||||||
try:
|
try:
|
||||||
i = int(arg)
|
i = int(arg)
|
||||||
@ -338,9 +364,26 @@ class CmdInterpreter(cmd.Cmd):
|
|||||||
self.__println("Be aware: indexes have been changed, rerun list before removing the next item.")
|
self.__println("Be aware: indexes have been changed, rerun list before removing the next item.")
|
||||||
self.__println("DO NOT FORGET TO SAVE AFTERWARDS!")
|
self.__println("DO NOT FORGET TO SAVE AFTERWARDS!")
|
||||||
|
|
||||||
def do_save(self, arg):
|
def __notify(self):
|
||||||
|
self.notifier.notify()
|
||||||
|
|
||||||
|
def do_notify(self, arg):
|
||||||
|
self.__notify()
|
||||||
|
|
||||||
|
def help_notify(self):
|
||||||
|
self.__println("Notifies threads using the list of datapoints about changes in this list.")
|
||||||
|
self.__println("Call after modifications on the list.")
|
||||||
|
|
||||||
|
def do_quit(self, arg):
|
||||||
|
self.__println("Bye!")
|
||||||
|
return True
|
||||||
|
|
||||||
|
def __save(self):
|
||||||
RegisterDatapoint.saveRegisterList(self.registers, self.config.registerFile)
|
RegisterDatapoint.saveRegisterList(self.registers, self.config.registerFile)
|
||||||
|
|
||||||
|
def do_save(self, arg):
|
||||||
|
self.__save()
|
||||||
|
|
||||||
def help_save(self):
|
def help_save(self):
|
||||||
self.__println("Usage: save")
|
self.__println("Usage: save")
|
||||||
self.__println("Saves a modified register list into the register file.")
|
self.__println("Saves a modified register list into the register file.")
|
||||||
@ -385,9 +428,9 @@ class CmdServer(threading.Thread):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
self.config = config
|
self.config = config
|
||||||
self.server = MyThreadingTCPServer((config.cmdAddress, config.cmdPort), CmdHandle, MyCmdUserData(config, notifier, registers))
|
self.server = MyThreadingTCPServer((config.cmdAddress, config.cmdPort), CmdHandle, MyCmdUserData(config, notifier, registers))
|
||||||
self.daemon = True
|
# self.daemon = True
|
||||||
|
|
||||||
def start(self):
|
def run(self):
|
||||||
self.server.serve_forever()
|
self.server.serve_forever()
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,7 +3,8 @@ import datetime
|
|||||||
# import RS485Ext
|
# import RS485Ext
|
||||||
import RegisterDatapoint
|
import RegisterDatapoint
|
||||||
from pymodbus.client.sync import ModbusSerialClient
|
from pymodbus.client.sync import ModbusSerialClient
|
||||||
import wiringpi
|
# import wiringpi
|
||||||
|
import Pins
|
||||||
import MyRS485
|
import MyRS485
|
||||||
import time
|
import time
|
||||||
import logging
|
import logging
|
||||||
@ -17,9 +18,9 @@ class CommunicationProcessor(threading.Thread):
|
|||||||
self.config = config
|
self.config = config
|
||||||
self.queue = queue
|
self.queue = queue
|
||||||
self.pubQueue = pubQueue
|
self.pubQueue = pubQueue
|
||||||
wiringpi.wiringPiSetup()
|
# wiringpi.wiringPiSetup()
|
||||||
wiringpi.pinMode(ERROR_PIN, wiringpi.OUTPUT)
|
# wiringpi.pinMode(ERROR_PIN, wiringpi.OUTPUT)
|
||||||
self.daemon = True
|
# self.daemon = True
|
||||||
if self.config.modbusDebug:
|
if self.config.modbusDebug:
|
||||||
logging.getLogger('pymodbus').setLevel(logging.DEBUG)
|
logging.getLogger('pymodbus').setLevel(logging.DEBUG)
|
||||||
else:
|
else:
|
||||||
@ -41,12 +42,14 @@ class CommunicationProcessor(threading.Thread):
|
|||||||
while True:
|
while True:
|
||||||
r = self.queue.get()
|
r = self.queue.get()
|
||||||
try:
|
try:
|
||||||
wiringpi.digitalWrite(ERROR_PIN, wiringpi.LOW)
|
# wiringpi.digitalWrite(ERROR_PIN, wiringpi.LOW)
|
||||||
|
Pins.pinsWrite('ERROR', False)
|
||||||
self.logger.debug("Dequeued: {0!s}".format(r))
|
self.logger.debug("Dequeued: {0!s}".format(r))
|
||||||
r.enqueued = False
|
r.enqueued = False
|
||||||
r.process(client, self.pubQueue)
|
r.process(client, self.pubQueue)
|
||||||
except RegisterDatapoint.DatapointException as e:
|
except RegisterDatapoint.DatapointException as e:
|
||||||
wiringpi.digitalWrite(ERROR_PIN, wiringpi.HIGH)
|
# wiringpi.digitalWrite(ERROR_PIN, wiringpi.HIGH)
|
||||||
|
Pins.pinsWrite('ERROR', True)
|
||||||
self.logger.error("ERROR when processing '{0}': {1!s}".format(r.label, e))
|
self.logger.error("ERROR when processing '{0}': {1!s}".format(r.label, e))
|
||||||
if client.socket is None:
|
if client.socket is None:
|
||||||
self.logger.error("renew socket")
|
self.logger.error("renew socket")
|
||||||
|
@ -13,3 +13,5 @@ class Config(object):
|
|||||||
self.serialPort = '/dev/ttyAMA0'
|
self.serialPort = '/dev/ttyAMA0'
|
||||||
self.serialBaudRate = 9600
|
self.serialBaudRate = 9600
|
||||||
self.interCommDelay = 0.025
|
self.interCommDelay = 0.025
|
||||||
|
self.heartbeatTopic = 'IoT/Heartbeat/Modbus2'
|
||||||
|
self.heartbeatPeriod = 10.0
|
||||||
|
20
src/Heartbeat.py
Normal file
20
src/Heartbeat.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import threading
|
||||||
|
import MqttProcessor
|
||||||
|
import logging
|
||||||
|
import time
|
||||||
|
|
||||||
|
class Heartbeat(threading.Thread):
|
||||||
|
def __init__(self, config, pubQueue):
|
||||||
|
super().__init__()
|
||||||
|
self.config = config
|
||||||
|
self.pubQueue = pubQueue
|
||||||
|
# self.daemon = True
|
||||||
|
self.logger = logging.getLogger('Heartbeat')
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
cnt = 0
|
||||||
|
while True:
|
||||||
|
cnt += 1
|
||||||
|
pubItem = MqttProcessor.PublishItem(self.config.heartbeatTopic, str(cnt))
|
||||||
|
self.pubQueue.put(pubItem)
|
||||||
|
time.sleep(self.config.heartbeatPeriod)
|
@ -2,13 +2,16 @@ import threading
|
|||||||
import paho.mqtt.client as mqtt
|
import paho.mqtt.client as mqtt
|
||||||
from NotificationForwarder import AbstractNotificationReceiver
|
from NotificationForwarder import AbstractNotificationReceiver
|
||||||
import logging
|
import logging
|
||||||
|
import Pins
|
||||||
|
|
||||||
class PublishItem(object):
|
class PublishItem(object):
|
||||||
def __init__(self, topic, payload):
|
def __init__(self, topic, payload):
|
||||||
self.topic = topic
|
self.topic = topic
|
||||||
self.payload = payload
|
self.payload = payload
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return 'Topic: {0}, Payload: {1}'.format(self.topic, self.payload)
|
||||||
|
|
||||||
def mqttOnConnectCallback(client, userdata, flags, rc):
|
def mqttOnConnectCallback(client, userdata, flags, rc):
|
||||||
userdata.onConnect()
|
userdata.onConnect()
|
||||||
|
|
||||||
@ -28,7 +31,7 @@ class MqttProcessor(threading.Thread, AbstractNotificationReceiver):
|
|||||||
self.client = mqtt.Client(userdata=self)
|
self.client = mqtt.Client(userdata=self)
|
||||||
self.subscriptions = []
|
self.subscriptions = []
|
||||||
self.topicRegisterMap ={}
|
self.topicRegisterMap ={}
|
||||||
self.daemon = True
|
# self.daemon = True
|
||||||
self.logger = logging.getLogger('MqttProcessor')
|
self.logger = logging.getLogger('MqttProcessor')
|
||||||
|
|
||||||
def __processUpdatedRegisters(self, force=False):
|
def __processUpdatedRegisters(self, force=False):
|
||||||
@ -67,7 +70,9 @@ class MqttProcessor(threading.Thread, AbstractNotificationReceiver):
|
|||||||
while True:
|
while True:
|
||||||
pubItem = self.pubQueue.get()
|
pubItem = self.pubQueue.get()
|
||||||
if isinstance(pubItem, PublishItem):
|
if isinstance(pubItem, PublishItem):
|
||||||
|
self.logger.debug('Publishing {0!s}'.format(pubItem))
|
||||||
self.client.publish(pubItem.topic, pubItem.payload)
|
self.client.publish(pubItem.topic, pubItem.payload)
|
||||||
|
Pins.pinsWrite('MSG', False)
|
||||||
else:
|
else:
|
||||||
self.logger.error("Invalid object in publish queue")
|
self.logger.error("Invalid object in publish queue")
|
||||||
|
|
||||||
@ -80,6 +85,7 @@ class MqttProcessor(threading.Thread, AbstractNotificationReceiver):
|
|||||||
self.logger.error("Disconnected from MQTT broker: {0}".format(rc))
|
self.logger.error("Disconnected from MQTT broker: {0}".format(rc))
|
||||||
|
|
||||||
def onMessage(self, topic, payload):
|
def onMessage(self, topic, payload):
|
||||||
|
Pins.pinsWrite('MSG', True)
|
||||||
# print("MqttProcessor.onMessage")
|
# print("MqttProcessor.onMessage")
|
||||||
r = self.topicRegisterMap[topic]
|
r = self.topicRegisterMap[topic]
|
||||||
self.logger.debug("{0}: {1!s} -> {2!s}".format(topic, payload, r))
|
self.logger.debug("{0}: {1!s} -> {2!s}".format(topic, payload, r))
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import serial
|
import serial
|
||||||
import wiringpi
|
# import wiringpi
|
||||||
|
import Pins
|
||||||
import array
|
import array
|
||||||
import fcntl
|
import fcntl
|
||||||
import termios
|
import termios
|
||||||
@ -9,16 +10,18 @@ DE_PIN = 0
|
|||||||
class MyRS485(serial.Serial):
|
class MyRS485(serial.Serial):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
wiringpi.wiringPiSetup()
|
# wiringpi.wiringPiSetup()
|
||||||
wiringpi.pinMode(DE_PIN, wiringpi.OUTPUT)
|
# wiringpi.pinMode(DE_PIN, wiringpi.OUTPUT)
|
||||||
self.buf = array.array('h', [0])
|
self.buf = array.array('h', [0])
|
||||||
|
|
||||||
def write(self, b):
|
def write(self, b):
|
||||||
wiringpi.digitalWrite(DE_PIN, wiringpi.HIGH)
|
# wiringpi.digitalWrite(DE_PIN, wiringpi.HIGH)
|
||||||
|
Pins.pinsWrite('DE', True)
|
||||||
super().write(b)
|
super().write(b)
|
||||||
while True:
|
while True:
|
||||||
fcntl.ioctl(self.fileno(), termios.TIOCSERGETLSR, self.buf, 1)
|
fcntl.ioctl(self.fileno(), termios.TIOCSERGETLSR, self.buf, 1)
|
||||||
if self.buf[0] & termios.TIOCSER_TEMT:
|
if self.buf[0] & termios.TIOCSER_TEMT:
|
||||||
break
|
break
|
||||||
wiringpi.digitalWrite(DE_PIN, wiringpi.LOW)
|
# wiringpi.digitalWrite(DE_PIN, wiringpi.LOW)
|
||||||
|
Pins.pinsWrite('DE', False)
|
||||||
|
|
||||||
|
24
src/Pins.py
Normal file
24
src/Pins.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import wiringpi
|
||||||
|
|
||||||
|
|
||||||
|
PINS = {
|
||||||
|
'DE': 0,
|
||||||
|
'ERROR': 29,
|
||||||
|
'MSG': 28
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def pinsInit():
|
||||||
|
wiringpi.wiringPiSetup()
|
||||||
|
for pin in PINS.values():
|
||||||
|
wiringpi.pinMode(pin, wiringpi.OUTPUT)
|
||||||
|
|
||||||
|
|
||||||
|
def pinsWrite(pinName, v):
|
||||||
|
if v:
|
||||||
|
pinState = wiringpi.HIGH
|
||||||
|
else:
|
||||||
|
pinState = wiringpi.LOW
|
||||||
|
wiringpi.digitalWrite(PINS[pinName], pinState)
|
||||||
|
|
@ -74,14 +74,14 @@ class HoldingRegisterDatapoint(AbstractModbusDatapoint):
|
|||||||
self.writeCount += 1
|
self.writeCount += 1
|
||||||
values = None
|
values = None
|
||||||
logger.debug("{0}: raw: {1!s}".format(self.label, self.writeRequestValue))
|
logger.debug("{0}: raw: {1!s}".format(self.label, self.writeRequestValue))
|
||||||
if self.converter and Converters.Converters[self.converter]['out']:
|
try:
|
||||||
try:
|
if self.converter and Converters.Converters[self.converter]['out']:
|
||||||
values = Converters.Converters[self.converter]['out'](self.writeRequestValue)
|
values = Converters.Converters[self.converter]['out'](self.writeRequestValue)
|
||||||
logger.debug("{0}: converted: {1!s}".format(self.label, values))
|
logger.debug("{0}: converted: {1!s}".format(self.label, values))
|
||||||
except Exception as e:
|
else:
|
||||||
raise DatapointException("Exception caught when trying to converter modbus data: {0!s}".format(e))
|
values = [int(self.writeRequestValue)]
|
||||||
else:
|
except Exception as e:
|
||||||
values = [int(self.writeRequestValue)]
|
raise DatapointException("Exception caught when trying to converter modbus data: {0!s}".format(e))
|
||||||
result = client.write_registers(address=self.address,
|
result = client.write_registers(address=self.address,
|
||||||
unit=self.unit,
|
unit=self.unit,
|
||||||
values=values)
|
values=values)
|
||||||
@ -99,14 +99,14 @@ class HoldingRegisterDatapoint(AbstractModbusDatapoint):
|
|||||||
raise DatapointException(result)
|
raise DatapointException(result)
|
||||||
logger.debug("{0}: {1!s}".format(self.label, result.registers))
|
logger.debug("{0}: {1!s}".format(self.label, result.registers))
|
||||||
value = None
|
value = None
|
||||||
if self.converter and Converters.Converters[self.converter]['in']:
|
try:
|
||||||
try:
|
if self.converter and Converters.Converters[self.converter]['in']:
|
||||||
value = Converters.Converters[self.converter]['in'](result.registers)
|
value = Converters.Converters[self.converter]['in'](result.registers)
|
||||||
logger.debug("{0}: converted: {1!s}".format(self.label, value))
|
logger.debug("{0}: converted: {1!s}".format(self.label, value))
|
||||||
except Exception as e:
|
else:
|
||||||
raise DatapointException("Exception caught when trying to converter modbus data: {0!s}".format(e))
|
value = result.registers
|
||||||
else:
|
except Exception as e:
|
||||||
value = result.registers
|
raise DatapointException("Exception caught when trying to converter modbus data: {0!s}".format(e))
|
||||||
if self.publishTopic:
|
if self.publishTopic:
|
||||||
pubQueue.put(MqttProcessor.PublishItem(self.publishTopic, str(value)))
|
pubQueue.put(MqttProcessor.PublishItem(self.publishTopic, str(value)))
|
||||||
self.lastContact = datetime.datetime.now()
|
self.lastContact = datetime.datetime.now()
|
||||||
@ -128,11 +128,11 @@ class CoilDatapoint(AbstractModbusDatapoint):
|
|||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return ("{0}, {1}: unit: {2}, address: {3}, scanRate: {4}, "
|
return ("{0}, {1}: unit: {2}, address: {3}, scanRate: {4}, "
|
||||||
"enqueued: {5}, lastContact: {6}, errorCount: {7}, processCount: {8}, "
|
"enqueued: {5}, lastContact: {6}, errorCount: {7}, readCount: {8}, "
|
||||||
"publishTopic: {9}, subscribeTopic: {10}, feedbackTopic: {11}"
|
"writeCount: {9}, publishTopic: {10}, subscribeTopic: {11}, feedbackTopic: {12}"
|
||||||
.format(self.type, self.label, self.unit, self.address,
|
.format(self.type, self.label, self.unit, self.address,
|
||||||
self.scanRate, self.enqueued, self.lastContact,
|
self.scanRate, self.enqueued, self.lastContact,
|
||||||
self.errorCount, self.processCount,
|
self.errorCount, self.readCount, self.writeCount,
|
||||||
self.publishTopic, self.subscribeTopic, self.feedbackTopic))
|
self.publishTopic, self.subscribeTopic, self.feedbackTopic))
|
||||||
|
|
||||||
def onMessage(self, value):
|
def onMessage(self, value):
|
||||||
@ -210,14 +210,14 @@ class InputRegisterDatapoint(ReadOnlyDatapoint):
|
|||||||
self.lastValue = result.registers
|
self.lastValue = result.registers
|
||||||
logger.debug("{0}: raw: {1!s}".format(self.label, result.registers))
|
logger.debug("{0}: raw: {1!s}".format(self.label, result.registers))
|
||||||
value = None
|
value = None
|
||||||
if self.converter and Converters.Converters[self.converter]['in']:
|
try:
|
||||||
try:
|
if self.converter and Converters.Converters[self.converter]['in']:
|
||||||
value = Converters.Converters[self.converter]['in'](result.registers)
|
value = Converters.Converters[self.converter]['in'](result.registers)
|
||||||
logger.debug("{0}: converted: {1!s}".format(self.label, value))
|
logger.debug("{0}: converted: {1!s}".format(self.label, value))
|
||||||
except Exception as e:
|
else:
|
||||||
raise DatapointException("Exception caught when trying to converter modbus data: {0!s}".format(e))
|
value = result.registers
|
||||||
else:
|
except Exception as e:
|
||||||
value = result.registers
|
raise DatapointException("Exception caught when trying to converter modbus data: {0!s}".format(e))
|
||||||
if self.publishTopic:
|
if self.publishTopic:
|
||||||
pubQueue.put(MqttProcessor.PublishItem(self.publishTopic, str(value)))
|
pubQueue.put(MqttProcessor.PublishItem(self.publishTopic, str(value)))
|
||||||
self.lastContact = datetime.datetime.now()
|
self.lastContact = datetime.datetime.now()
|
||||||
|
@ -10,7 +10,7 @@ class ScanRateConsideringQueueFeeder(threading.Thread, AbstractNotificationRecei
|
|||||||
self.registers = registers
|
self.registers = registers
|
||||||
self.queue = queue
|
self.queue = queue
|
||||||
self.delayEvent = threading.Event()
|
self.delayEvent = threading.Event()
|
||||||
self.daemon = True
|
# self.daemon = True
|
||||||
self.logger = logging.getLogger('ScanRateConsideringQueueFeeder')
|
self.logger = logging.getLogger('ScanRateConsideringQueueFeeder')
|
||||||
|
|
||||||
def getMinimalScanrate(self):
|
def getMinimalScanrate(self):
|
||||||
|
@ -10,8 +10,8 @@ import datetime
|
|||||||
import RegisterDatapoint
|
import RegisterDatapoint
|
||||||
import pickle
|
import pickle
|
||||||
import logging
|
import logging
|
||||||
|
import Pins
|
||||||
|
import Heartbeat
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
@ -29,6 +29,8 @@ if __name__ == "__main__":
|
|||||||
logger.addHandler(fh)
|
logger.addHandler(fh)
|
||||||
logger.addHandler(ch)
|
logger.addHandler(ch)
|
||||||
|
|
||||||
|
Pins.pinsInit()
|
||||||
|
|
||||||
queue = MyPriorityQueue.MyPriorityQueue()
|
queue = MyPriorityQueue.MyPriorityQueue()
|
||||||
pubQueue = Queue()
|
pubQueue = Queue()
|
||||||
nf = NotificationForwarder.NotificationForwarder()
|
nf = NotificationForwarder.NotificationForwarder()
|
||||||
@ -47,11 +49,15 @@ if __name__ == "__main__":
|
|||||||
mp.start()
|
mp.start()
|
||||||
logger.debug('MqttProcessor started')
|
logger.debug('MqttProcessor started')
|
||||||
|
|
||||||
|
cs = CmdServer.CmdServer(config, nf, datapoints)
|
||||||
|
cs.start()
|
||||||
|
logger.debug('CmdServer started')
|
||||||
|
|
||||||
|
hb = Heartbeat.Heartbeat(config, pubQueue)
|
||||||
|
hb.start()
|
||||||
|
logger.debug('Heartbeat started')
|
||||||
|
|
||||||
qf = ScanRateConsideringQueueFeeder.ScanRateConsideringQueueFeeder(config, datapoints, queue)
|
qf = ScanRateConsideringQueueFeeder.ScanRateConsideringQueueFeeder(config, datapoints, queue)
|
||||||
nf.register(qf)
|
nf.register(qf)
|
||||||
qf.start()
|
qf.start()
|
||||||
logger.debug('ScanRateConsideringQueueFeeder started')
|
logger.debug('ScanRateConsideringQueueFeeder started')
|
||||||
|
|
||||||
cs = CmdServer.CmdServer(config, nf, datapoints)
|
|
||||||
cs.start()
|
|
||||||
logger.debug('CmdServer started')
|
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
"converter": "dht20TOFloat",
|
"converter": "dht20TOFloat",
|
||||||
"count": 1,
|
"count": 1,
|
||||||
"label": "Temperature",
|
"label": "Temperature",
|
||||||
"publishTopic": "Pub/Temperature",
|
"publishTopic": "IoT/Measurment/Modbus2/Laundry/Temperature",
|
||||||
"scanRate": 10.0,
|
"scanRate": 60.0,
|
||||||
"unit": 5,
|
"unit": 5,
|
||||||
"updateOnly": false
|
"updateOnly": false
|
||||||
},
|
},
|
||||||
@ -18,8 +18,8 @@
|
|||||||
"converter": "dht20TOFloat",
|
"converter": "dht20TOFloat",
|
||||||
"count": 1,
|
"count": 1,
|
||||||
"label": "Humidity",
|
"label": "Humidity",
|
||||||
"publishTopic": "Pub/Humidity",
|
"publishTopic": "IoT/Measurment/Modbus2/Laundry/Humidity",
|
||||||
"scanRate": null,
|
"scanRate": 60.0,
|
||||||
"unit": 5,
|
"unit": 5,
|
||||||
"updateOnly": false
|
"updateOnly": false
|
||||||
},
|
},
|
||||||
@ -33,7 +33,7 @@
|
|||||||
"count": 1,
|
"count": 1,
|
||||||
"label": "Switches",
|
"label": "Switches",
|
||||||
"publishTopic": "Pub/Switches",
|
"publishTopic": "Pub/Switches",
|
||||||
"scanRate": null,
|
"scanRate": 0.5,
|
||||||
"unit": 4,
|
"unit": 4,
|
||||||
"updateOnly": false
|
"updateOnly": false
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user