Updates for MAXH2O-91
This commit is contained in:
@@ -155,18 +155,21 @@ class Channel(object):
|
||||
"""Read the value."""
|
||||
pass
|
||||
|
||||
|
||||
def identity(sent):
|
||||
"""Returns exactly what was sent to it."""
|
||||
"""Return exactly what was sent to it."""
|
||||
return sent
|
||||
|
||||
|
||||
class ModbusChannel(Channel):
|
||||
"""Modbus channel object."""
|
||||
|
||||
def __init__(self, mesh_name, register_number, data_type, chg_threshold, guarantee_sec, map_=False, write_enabled=False, transformFn=identity):
|
||||
def __init__(self, mesh_name, register_number, data_type, chg_threshold, guarantee_sec, channel_size=1, map_=False, write_enabled=False, transformFn=identity):
|
||||
"""Initialize the channel."""
|
||||
super(ModbusChannel, self).__init__(mesh_name, data_type, chg_threshold, guarantee_sec, map_, write_enabled)
|
||||
self.mesh_name = mesh_name
|
||||
self.register_number = register_number
|
||||
self.channel_size = channel_size
|
||||
self.data_type = data_type
|
||||
self.last_value = None
|
||||
self.value = None
|
||||
@@ -178,6 +181,7 @@ class ModbusChannel(Channel):
|
||||
self.transformFn = transformFn
|
||||
|
||||
def read(self, mbsvalue):
|
||||
"""Return the transformed read value."""
|
||||
return self.transformFn(mbsvalue)
|
||||
|
||||
|
||||
@@ -209,8 +213,10 @@ class PLCChannel(Channel):
|
||||
|
||||
return plc_value
|
||||
|
||||
|
||||
class BoolArrayChannels(Channel):
|
||||
"""Hold the configuration for a set of boolean array channels."""
|
||||
|
||||
def __init__(self, ip, mesh_name, plc_tag, data_type, chg_threshold, guarantee_sec, map_=False, write_enabled=False):
|
||||
"""Initialize the channel."""
|
||||
self.plc_ip = ip
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
"""Holds map values for prostarsolar."""
|
||||
|
||||
def charge_state(inp_state):
|
||||
"""Map function for charge state."""
|
||||
states = {
|
||||
0: "Start",
|
||||
1: "Night Check",
|
||||
2: "Disconnect",
|
||||
3: "Night",
|
||||
4: "Fault",
|
||||
5: "Bulk",
|
||||
6: "Absorption",
|
||||
7: "Float",
|
||||
8: "Equalize"
|
||||
}
|
||||
if inp_state in range(0,9):
|
||||
return states[inp_state]
|
||||
else:
|
||||
return inp_state
|
||||
|
||||
|
||||
def array_faults(inp_array_faults):
|
||||
"""Form a string for the array_faults."""
|
||||
fault_string = ""
|
||||
faults = {
|
||||
0: "Overcurrent Phase 1",
|
||||
1: "FETs Shorted",
|
||||
2: "Software Bug",
|
||||
3: "Battery HVD (High Voltage Disconnect)",
|
||||
4: "Array HVD (High Voltage Disconnect)",
|
||||
5: "EEPROM Setting Edit (reset required)",
|
||||
6: "RTS Shorted",
|
||||
7: "RTS was valid now disconnected",
|
||||
8: "Local temp. sensor failed",
|
||||
9: "Battery LVD (Low Voltage Disconect)",
|
||||
10: "DIP Switch Changed (excl. DIP 8)",
|
||||
11: "Processor Supply Fault"
|
||||
}
|
||||
|
||||
bit_string = ("0" * 16 + "{0:b}".format(inp_array_faults))[-16:]
|
||||
for i in range(0, 12):
|
||||
if int(bit_string[i]) == 1:
|
||||
fault_string += faults[i] + ", "
|
||||
if fault_string:
|
||||
return fault_string[:-2]
|
||||
else:
|
||||
return "None"
|
||||
@@ -1,13 +1,12 @@
|
||||
{
|
||||
"name": "prostarsolar",
|
||||
"driverFilename": "prostarsolar.py",
|
||||
"driverId": "0000",
|
||||
"name": "prostarsolar",
|
||||
"driverFilename": "prostarsolar.py",
|
||||
"driverId": "0000",
|
||||
"additionalDriverFiles": [
|
||||
"utilities.py",
|
||||
"persistence.py",
|
||||
"Channel.py",
|
||||
"Maps.py"
|
||||
],
|
||||
"version": 1,
|
||||
"persistence.py",
|
||||
"Channel.py"
|
||||
],
|
||||
"version": 1,
|
||||
"s3BucketName": "prostarsolar"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,20 +2,67 @@
|
||||
|
||||
import threading
|
||||
from device_base import deviceBase
|
||||
from Channel import read_tag, write_tag
|
||||
from Channel import ModbusChannel
|
||||
from Maps import charge_state, array_faults
|
||||
import persistence
|
||||
from random import randint
|
||||
from utilities import get_public_ip_address, int_to_float16
|
||||
import json
|
||||
import time
|
||||
|
||||
import minimalmodbus
|
||||
import minimalmodbusM1
|
||||
|
||||
minimalmodbusM1.CLOSE_PORT_AFTER_EACH_CALL = True
|
||||
minimalmodbusM1.STOPBITS = 2
|
||||
|
||||
_ = None
|
||||
|
||||
|
||||
def charge_state(inp_state):
|
||||
"""Map function for charge state."""
|
||||
states = {
|
||||
0: "Start",
|
||||
1: "Night Check",
|
||||
2: "Disconnect",
|
||||
3: "Night",
|
||||
4: "Fault",
|
||||
5: "Bulk",
|
||||
6: "Absorption",
|
||||
7: "Float",
|
||||
8: "Equalize"
|
||||
}
|
||||
if inp_state in range(0, 9):
|
||||
return states[inp_state]
|
||||
else:
|
||||
return inp_state
|
||||
|
||||
|
||||
def array_faults(inp_array_faults):
|
||||
"""Form a string for the array_faults."""
|
||||
fault_string = ""
|
||||
faults = {
|
||||
0: "Overcurrent Phase 1",
|
||||
1: "FETs Shorted",
|
||||
2: "Software Bug",
|
||||
3: "Battery HVD (High Voltage Disconnect)",
|
||||
4: "Array HVD (High Voltage Disconnect)",
|
||||
5: "EEPROM Setting Edit (reset required)",
|
||||
6: "RTS Shorted",
|
||||
7: "RTS was valid now disconnected",
|
||||
8: "Local temp. sensor failed",
|
||||
9: "Battery LVD (Low Voltage Disconect)",
|
||||
10: "DIP Switch Changed (excl. DIP 8)",
|
||||
11: "Processor Supply Fault"
|
||||
}
|
||||
|
||||
bit_string = ("0" * 16 + "{0:b}".format(inp_array_faults))[-16:]
|
||||
for i in range(0, 12):
|
||||
if int(bit_string[i]) == 1:
|
||||
fault_string += faults[i] + ", "
|
||||
if fault_string:
|
||||
return fault_string[:-2]
|
||||
else:
|
||||
return "None"
|
||||
|
||||
|
||||
# GLOBAL VARIABLES
|
||||
WATCHDOG_SEND_PERIOD = 3600 # Seconds, the longest amount of time before sending the watchdog status
|
||||
PLC_IP_ADDRESS = "192.168.1.10"
|
||||
@@ -78,8 +125,8 @@ class start(threading.Thread, deviceBase):
|
||||
connected_to_485 = self.mcu.set485Baud(9600)
|
||||
|
||||
serial_485 = self.mcu.rs485
|
||||
instrument_485 = minimalmodbusM1.Instrument(1, serial_485)
|
||||
instrument_485.address = 1
|
||||
instrument_485 = minimalmodbusM1.Instrument(21, serial_485)
|
||||
instrument_485.address = 21
|
||||
|
||||
send_loops = 0
|
||||
watchdog_loops = 0
|
||||
@@ -95,17 +142,19 @@ class start(threading.Thread, deviceBase):
|
||||
self.sendtodbDev(1, chan.mesh_name, chan.value, 0, 'prostarsolar')
|
||||
time.sleep(0.1)
|
||||
except IOError as e:
|
||||
print("IO Error: {}".format(e))
|
||||
print("prostarsolar IO Error: {}".format(e))
|
||||
print("Attempting to reconnect to rs485 device")
|
||||
connected_to_485 = False
|
||||
while connected_to_485 is False:
|
||||
connected_to_485 = self.mcu.set485Baud(9600)
|
||||
|
||||
serial_485 = self.mcu.rs485
|
||||
instrument_485 = minimalmodbusM1.Instrument(1, serial_485)
|
||||
instrument_485.address = 1
|
||||
instrument_485 = minimalmodbusM1.Instrument(21, serial_485)
|
||||
instrument_485.address = 21
|
||||
except Exception as e:
|
||||
print("prostarsolar Non-IO Error: {}".format(e))
|
||||
|
||||
# print("prostarsolar driver still alive...")
|
||||
print("prostarsolar driver still alive...")
|
||||
if self.forceSend:
|
||||
if send_loops > 2:
|
||||
print("Turning off forceSend")
|
||||
@@ -128,30 +177,8 @@ class start(threading.Thread, deviceBase):
|
||||
watchdog_loops = 0
|
||||
time.sleep(10)
|
||||
|
||||
def prostarsolar_watchdog(self):
|
||||
"""Write a random integer to the PLC and then 1 seconds later check that it has been decremented by 1."""
|
||||
randval = randint(0, 32767)
|
||||
write_tag(str(PLC_IP_ADDRESS), 'watchdog_INT', randval)
|
||||
time.sleep(1)
|
||||
watchdog_val = read_tag(str(PLC_IP_ADDRESS), 'watchdog_INT')
|
||||
try:
|
||||
return (randval - 1) == watchdog_val[0]
|
||||
except (KeyError, TypeError):
|
||||
return False
|
||||
|
||||
def prostarsolar_sync(self, name, value):
|
||||
"""Sync all data from the driver."""
|
||||
self.forceSend = True
|
||||
# self.sendtodb("log", "synced", 0)
|
||||
return True
|
||||
|
||||
def prostarsolar_writeplctag(self, name, value):
|
||||
"""Write a value to the PLC."""
|
||||
new_val = json.loads(str(value).replace("'", '"'))
|
||||
tag_n = str(new_val['tag']) # "cmd_Start"
|
||||
val_n = new_val['val']
|
||||
w = write_tag(str(PLC_IP_ADDRESS), tag_n, val_n)
|
||||
print("Result of prostarsolar_writeplctag(self, {}, {}) = {}".format(name, value, w))
|
||||
if w is None:
|
||||
w = "Error writing to PLC..."
|
||||
return w
|
||||
|
||||
Reference in New Issue
Block a user