jsonifying register file done so far
This commit is contained in:
parent
2665fdd5e3
commit
d97b7469fe
14
snippets/test9.py
Normal file
14
snippets/test9.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
class A(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.a = 1
|
||||||
|
def x(self):
|
||||||
|
return self.a
|
||||||
|
|
||||||
|
class B(A):
|
||||||
|
def __init__(self):
|
||||||
|
self.a = 2
|
||||||
|
def x(self):
|
||||||
|
return self.a
|
||||||
|
def y(self):
|
||||||
|
return super().x()
|
||||||
|
|
@ -309,23 +309,17 @@ class CmdInterpreter(cmd.Cmd):
|
|||||||
self.__println("DO NOT FORGET TO SAVE AFTERWARDS!")
|
self.__println("DO NOT FORGET TO SAVE AFTERWARDS!")
|
||||||
|
|
||||||
def do_save(self, arg):
|
def do_save(self, arg):
|
||||||
for i in self.registers:
|
RegisterDatapoint.saveRegisterFile(self.registers, self.config.registerFile)
|
||||||
self.logger.warn("{0!s}: {1!s}".format(i, i.__dict__))
|
|
||||||
with open(self.config.registerFile, 'wb') as f:
|
|
||||||
pickle.dump(self.registers, f)
|
|
||||||
|
|
||||||
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.")
|
||||||
|
|
||||||
def do_load(self, arg):
|
def do_load(self, arg):
|
||||||
registers = None
|
|
||||||
with open(self.config.registerFile, 'rb') as f:
|
|
||||||
registers = pickle.load(f)
|
|
||||||
try:
|
try:
|
||||||
RegisterDatapoint.checkRegisterList(registers)
|
registers = RegisterDatapoint.loadRegisterList(self.config.registerFile)
|
||||||
self.registers = registers
|
self.registers = registers
|
||||||
except ValueError as e:
|
except Exception as e:
|
||||||
self.__println("Unable to load register list: {0!s}".format(e))
|
self.__println("Unable to load register list: {0!s}".format(e))
|
||||||
|
|
||||||
def help_load(self):
|
def help_load(self):
|
||||||
|
@ -3,18 +3,45 @@ from pymodbus.pdu import ExceptionResponse
|
|||||||
from pymodbus.exceptions import ModbusIOException
|
from pymodbus.exceptions import ModbusIOException
|
||||||
import MqttProcessor
|
import MqttProcessor
|
||||||
import logging
|
import logging
|
||||||
|
import json
|
||||||
import pickle
|
import pickle
|
||||||
|
|
||||||
|
|
||||||
|
class JsonifyEncoder(json.JSONEncoder):
|
||||||
|
def default(self, o):
|
||||||
|
res = None
|
||||||
|
try:
|
||||||
|
res = o.jsonify()
|
||||||
|
except (TypeError, AttributeError):
|
||||||
|
if type(o) == datetime.timedelta:
|
||||||
|
res = o.total_seconds()
|
||||||
|
else:
|
||||||
|
res = super().default(o)
|
||||||
|
return res
|
||||||
|
|
||||||
|
def datapointObjectHook(j):
|
||||||
|
if type(j) == dict and 'type' in j and 'args' in j:
|
||||||
|
klass = eval(j['type'])
|
||||||
|
o = klass(**j['args'])
|
||||||
|
return o
|
||||||
|
else:
|
||||||
|
return j
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class DatapointException(Exception): pass
|
class DatapointException(Exception): pass
|
||||||
|
|
||||||
class AbstractModbusDatapoint(object):
|
class AbstractModbusDatapoint(object):
|
||||||
def __init__(self, label=None, unit=None, address=None, count=None, scanRate=None):
|
def __init__(self, label=None, unit=None, address=None, count=None, scanRate=None):
|
||||||
|
self.argList = ['label', 'unit', 'address', 'count', 'scanRate']
|
||||||
self.label = label
|
self.label = label
|
||||||
self.unit = unit
|
self.unit = unit
|
||||||
self.address = address
|
self.address = address
|
||||||
self.count = count
|
self.count = count
|
||||||
self.scanRate = scanRate
|
if type(scanRate) == float:
|
||||||
|
self.scanRate = datetime.timedelta(seconds=scanRate)
|
||||||
|
else:
|
||||||
|
self.scanRate = scanRate
|
||||||
self.type = 'abstract data point'
|
self.type = 'abstract data point'
|
||||||
self.enqueued = False
|
self.enqueued = False
|
||||||
self.lastContact = None
|
self.lastContact = None
|
||||||
@ -32,14 +59,21 @@ class AbstractModbusDatapoint(object):
|
|||||||
self.scanRate, self.enqueued, self.lastContact,
|
self.scanRate, self.enqueued, self.lastContact,
|
||||||
self.errorCount, self.processCount))
|
self.errorCount, self.processCount))
|
||||||
|
|
||||||
|
def jsonify(self):
|
||||||
|
return {'type':self.__class__.__name__,
|
||||||
|
'args': { k: getattr(self, k) for k in self.argList }
|
||||||
|
}
|
||||||
|
|
||||||
def process(self, client):
|
def process(self, client):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class HoldingRegisterDatapoint(AbstractModbusDatapoint):
|
class HoldingRegisterDatapoint(AbstractModbusDatapoint):
|
||||||
def __init__(self, label=None, unit=None, address=None, count=None, scanRate=None,
|
def __init__(self, label=None, unit=None, address=None, count=None, scanRate=None,
|
||||||
publishTopic=None, subscribeTopic=None, feedbackTopic=None):
|
publishTopic=None, subscribeTopic=None, feedbackTopic=None):
|
||||||
super().__init__(label, unit, address, count, scanRate)
|
super().__init__(label, unit, address, count, scanRate)
|
||||||
|
self.argList = self.argList + ['publishTopic', 'subscribeTopic', 'feedbackTopic']
|
||||||
self.publishTopic = publishTopic
|
self.publishTopic = publishTopic
|
||||||
self.subscribeTopic = subscribeTopic
|
self.subscribeTopic = subscribeTopic
|
||||||
self.feedbackTopic = feedbackTopic
|
self.feedbackTopic = feedbackTopic
|
||||||
@ -79,6 +113,7 @@ class HoldingRegisterDatapoint(AbstractModbusDatapoint):
|
|||||||
class ReadOnlyDatapoint(AbstractModbusDatapoint):
|
class ReadOnlyDatapoint(AbstractModbusDatapoint):
|
||||||
def __init__(self, label=None, unit=None, address=None, count=None, scanRate=None, updateOnly=None, publishTopic=None):
|
def __init__(self, label=None, unit=None, address=None, count=None, scanRate=None, updateOnly=None, publishTopic=None):
|
||||||
super().__init__(label, unit, address, count, scanRate)
|
super().__init__(label, unit, address, count, scanRate)
|
||||||
|
self.argList = self.argList + ['updateOnly', 'publishTopic']
|
||||||
self.updateOnly = updateOnly
|
self.updateOnly = updateOnly
|
||||||
self.lastValue = None
|
self.lastValue = None
|
||||||
self.publishTopic = publishTopic
|
self.publishTopic = publishTopic
|
||||||
@ -137,39 +172,14 @@ class DiscreteInputDatapoint(ReadOnlyDatapoint):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def loadRegisterList(registerList):
|
def saveRegisterList(registerList, registerListFile):
|
||||||
# Load, check and auto-update registers file
|
js = json.dumps(registerList, cls=JsonifyEncoder, sort_keys=True, indent=4)
|
||||||
|
with open(registerListFile, 'w') as f:
|
||||||
with open(registerList, 'rb') as f:
|
f.write(js)
|
||||||
datapoints = pickle.load(f)
|
|
||||||
|
def loadRegisterList(registerListFile):
|
||||||
checkRegisterList(datapoints)
|
with open(registerListFile, 'r') as f:
|
||||||
|
js = f.read()
|
||||||
newDatapoints = []
|
registerList = json.loads(js, object_hook=datapointObjectHook)
|
||||||
for dp in datapoints:
|
return registerList
|
||||||
ndp = type(dp)()
|
|
||||||
for k,v in dp.__dict__.items():
|
|
||||||
ndp.__dict__[k] = v
|
|
||||||
newDatapoints.append(ndp)
|
|
||||||
logging.getLogger('loadRegisterList').debug("Datapoint loaded: {0!s}".format(ndp))
|
|
||||||
|
|
||||||
checkRegisterList(newDatapoints, reset=True)
|
|
||||||
|
|
||||||
with open(registerList, 'wb') as f:
|
|
||||||
pickle.dump(newDatapoints, f)
|
|
||||||
|
|
||||||
return newDatapoints
|
|
||||||
|
|
||||||
|
|
||||||
def checkRegisterList(registers, reset=False):
|
|
||||||
for r in registers:
|
|
||||||
if not isinstance(r, AbstractModbusDatapoint):
|
|
||||||
raise ValueError('Entry in register list {0!s} is not derived from class AbstractModbusDatapoint'.format(r))
|
|
||||||
else:
|
|
||||||
if reset:
|
|
||||||
r.errorCount = 0
|
|
||||||
r.processCount = 0
|
|
||||||
r.enqueued = False
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
6
src/loadRegisterFile.py
Normal file
6
src/loadRegisterFile.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import RegisterDatapoint
|
||||||
|
|
||||||
|
registers = RegisterDatapoint.loadRegisterList('registers.json')
|
||||||
|
|
||||||
|
for r in registers:
|
||||||
|
print("{0!s}".format(r))
|
129
src/registers.json
Normal file
129
src/registers.json
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"args": {
|
||||||
|
"address": 1,
|
||||||
|
"count": 1,
|
||||||
|
"label": "Temperature",
|
||||||
|
"publishTopic": "Pub/Temperature",
|
||||||
|
"scanRate": 60.0,
|
||||||
|
"unit": 5,
|
||||||
|
"updateOnly": false
|
||||||
|
},
|
||||||
|
"type": "InputRegisterDatapoint"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"args": {
|
||||||
|
"address": 2,
|
||||||
|
"count": 1,
|
||||||
|
"label": "Humidity",
|
||||||
|
"publishTopic": "Pub/Humidity",
|
||||||
|
"scanRate": null,
|
||||||
|
"unit": 5,
|
||||||
|
"updateOnly": false
|
||||||
|
},
|
||||||
|
"type": "InputRegisterDatapoint"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"args": {
|
||||||
|
"address": 0,
|
||||||
|
"count": 1,
|
||||||
|
"label": "Switches",
|
||||||
|
"publishTopic": "Pub/Switches",
|
||||||
|
"scanRate": 60.0,
|
||||||
|
"unit": 4,
|
||||||
|
"updateOnly": false
|
||||||
|
},
|
||||||
|
"type": "DiscreteInputDatapoint"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"args": {
|
||||||
|
"address": 40010,
|
||||||
|
"count": 2,
|
||||||
|
"feedbackTopic": null,
|
||||||
|
"label": "Counter1",
|
||||||
|
"publishTopic": "Pub/Counter1",
|
||||||
|
"scanRate": 60.0,
|
||||||
|
"subscribeTopic": null,
|
||||||
|
"unit": 4
|
||||||
|
},
|
||||||
|
"type": "HoldingRegisterDatapoint"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"args": {
|
||||||
|
"address": 40012,
|
||||||
|
"count": 2,
|
||||||
|
"feedbackTopic": null,
|
||||||
|
"label": "Counter2",
|
||||||
|
"publishTopic": "Pub/Counter2",
|
||||||
|
"scanRate": 60.0,
|
||||||
|
"subscribeTopic": null,
|
||||||
|
"unit": 4
|
||||||
|
},
|
||||||
|
"type": "HoldingRegisterDatapoint"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"args": {
|
||||||
|
"address": 40014,
|
||||||
|
"count": 2,
|
||||||
|
"feedbackTopic": null,
|
||||||
|
"label": "Counter3",
|
||||||
|
"publishTopic": "Pub/Counter3",
|
||||||
|
"scanRate": 60.0,
|
||||||
|
"subscribeTopic": null,
|
||||||
|
"unit": 4
|
||||||
|
},
|
||||||
|
"type": "HoldingRegisterDatapoint"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"args": {
|
||||||
|
"address": 40016,
|
||||||
|
"count": 2,
|
||||||
|
"feedbackTopic": null,
|
||||||
|
"label": "Counter4",
|
||||||
|
"publishTopic": "Pub/Counter4",
|
||||||
|
"scanRate": 60.0,
|
||||||
|
"subscribeTopic": null,
|
||||||
|
"unit": 4
|
||||||
|
},
|
||||||
|
"type": "HoldingRegisterDatapoint"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"args": {
|
||||||
|
"address": 40001,
|
||||||
|
"count": 1,
|
||||||
|
"feedbackTopic": null,
|
||||||
|
"label": "Version",
|
||||||
|
"publishTopic": "Pub/Version",
|
||||||
|
"scanRate": 1.0,
|
||||||
|
"subscribeTopic": null,
|
||||||
|
"unit": 4
|
||||||
|
},
|
||||||
|
"type": "HoldingRegisterDatapoint"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"args": {
|
||||||
|
"address": 40001,
|
||||||
|
"count": 1,
|
||||||
|
"feedbackTopic": null,
|
||||||
|
"label": "Version",
|
||||||
|
"publishTopic": "Pub/Version",
|
||||||
|
"scanRate": 10.0,
|
||||||
|
"subscribeTopic": null,
|
||||||
|
"unit": 4
|
||||||
|
},
|
||||||
|
"type": "HoldingRegisterDatapoint"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"args": {
|
||||||
|
"address": 40001,
|
||||||
|
"count": 1,
|
||||||
|
"feedbackTopic": "FB/Version",
|
||||||
|
"label": "Version_W",
|
||||||
|
"publishTopic": null,
|
||||||
|
"scanRate": 0.0,
|
||||||
|
"subscribeTopic": "Sub/Version",
|
||||||
|
"unit": 4
|
||||||
|
},
|
||||||
|
"type": "HoldingRegisterDatapoint"
|
||||||
|
}
|
||||||
|
]
|
@ -1,14 +1,12 @@
|
|||||||
import datetime
|
import datetime
|
||||||
import RegisterDatapoint
|
import RegisterDatapoint
|
||||||
import pickle
|
import pickle
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
with open('registers.pkl', 'rb') as f:
|
with open('registers.pkl', 'rb') as f:
|
||||||
datapoints = pickle.load(f)
|
datapoints = pickle.load(f)
|
||||||
|
|
||||||
RegisterDatapoint.checkRegisterList(datapoints, reset=True)
|
|
||||||
|
|
||||||
newDatapoints = []
|
newDatapoints = []
|
||||||
for dp in datapoints:
|
for dp in datapoints:
|
||||||
ndp = type(dp)()
|
ndp = type(dp)()
|
||||||
@ -17,9 +15,10 @@ for dp in datapoints:
|
|||||||
ndp.__dict__[k] = v
|
ndp.__dict__[k] = v
|
||||||
newDatapoints.append(ndp)
|
newDatapoints.append(ndp)
|
||||||
|
|
||||||
RegisterDatapoint.checkRegisterList(newDatapoints, reset=True)
|
|
||||||
|
|
||||||
with open('registers.pkl', 'wb') as f:
|
|
||||||
pickle.dump(newDatapoints, f)
|
|
||||||
|
|
||||||
|
js = json.dumps(newDatapoints, cls=RegisterDatapoint.JsonifyEncoder, sort_keys=True, indent=4)
|
||||||
|
print(js)
|
||||||
|
|
||||||
|
|
||||||
|
RegisterDatapoint.saveRegisterList(newDatapoints, 'registers.json')
|
Loading…
x
Reference in New Issue
Block a user