Updates for MAXH2O-91

This commit is contained in:
Patrick McDonagh
2017-12-21 17:05:18 -06:00
parent df0eb5cc7b
commit 3645e1a803
4 changed files with 75 additions and 90 deletions

View File

@@ -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

View File

@@ -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"

View File

@@ -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"
}
}

View File

@@ -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