Compare commits

..

No commits in common. "main" and "v0.0.43" have entirely different histories.

4 changed files with 121 additions and 199 deletions

View File

@ -1,49 +1,49 @@
{ {
"device": { "device": {
"enter": { "setzero": {
"action": "Off" "action": "Off"
}, },
"main": {
"action": "Off",
"duration": 4
},
"measure": { "measure": {
"action": "On" "action": "On"
}, },
"mixed": { "mixed": {
"action": "Off" "action": "Off"
}, },
"pure": {
"action": "Off",
"duration": 1.5
},
"enter":{
"action": "Off"
},
"vent": {
"action": "On"
},
"motor": { "motor": {
"action": "Off" "action": "Off"
}, },
"pure": { "main": {
"action": "Off", "action": "Off",
"duration": 4 "duration": 1.5
},
"setzero": {
"action": "Off"
},
"vent": {
"action": "Off"
} }
}, },
"working-time":{
"step0": 5,
"step1": 10,
"step2": 6,
"step3": 7,
"step4": 20,
"step5": 10,
"step6": 6,
"step7": 6,
"step8": 10,
"step9": 0.5
},
"maintenance": { "maintenance": {
"clean": { "clean": {
"duration": 20, "duration": 20,
"time": 25 "time": 25
} }
}, },
"type": "manual", "type": "manual"
"working-time": { }
"step0": 5,
"step1": 10,
"step2": 0.5,
"step3": 4,
"step4": 20,
"step5": 20,
"step6": 0.5,
"step7": 15,
"step8": 10,
"step9": 140
}
}

View File

@ -7,5 +7,5 @@ spec:
virtualEnv: base # 사용할 가상환경 이름입니다. virtualEnv: base # 사용할 가상환경 이름입니다.
package: requirements.txt # 설치할 Python 패키지 정보 파일입니다.(기본 값은 requirement.txt 입니다.) package: requirements.txt # 설치할 Python 패키지 정보 파일입니다.(기본 값은 requirement.txt 입니다.)
stackbase: stackbase:
tagName: v0.0.51 # Stackbase(gitea)에 릴리즈 태그명 입니다. tagName: v0.0.43 # Stackbase(gitea)에 릴리즈 태그명 입니다.
repoName: sampyo-dio # Stackbase(gitea)에 저장될 저장소 이릅니다. repoName: sampyo-dio # Stackbase(gitea)에 저장될 저장소 이릅니다.

264
main.py
View File

@ -1,5 +1,6 @@
import json import json
import time import time
import argparse
import sys, signal import sys, signal
import gpiod import gpiod
from pymodbus.client import ModbusTcpClient from pymodbus.client import ModbusTcpClient
@ -9,8 +10,6 @@ import pytz
from datetime import datetime from datetime import datetime
import threading, socket import threading, socket
import uuid import uuid
import logging
from logging.handlers import RotatingFileHandler
def Motor(chip, status, action): def Motor(chip, status, action):
if action == 'On': if action == 'On':
@ -44,93 +43,31 @@ def Valve_PureWater(chip, status, action, duration=7):
chip.set_values(status) chip.set_values(status)
time.sleep(0.05) time.sleep(0.05)
if pure_valve_status != 0 and action == 'Off': if action == 'On':
status[2] = 0
status[3] = 1
chip.set_values(status)
time.sleep(7)
pure_valve_status = 0
elif pure_valve_status == 0 and action == 'On':
status[2] = 1 status[2] = 1
status[3] = 0 status[3] = 0
chip.set_values(status) chip.set_values(status)
time.sleep(duration) time.sleep(duration)
if duration >= 7: else: # 'Off'
pure_valve_status = 2 if pure_value_status != 0:
elif duration < 7: status[2] = 0
pure_valve_status = 1 status[3] = 1
chip.set_values(status)
time.sleep(7)
status[2] = 0 status[2] = 0
status[3] = 0 status[3] = 0
chip.set_values(status) chip.set_values(status)
time.sleep(0.05) time.sleep(0.05)
# def Valve_EnterWater(chip, status, action): if action == 'On' and duration >= 7:
def Valve_EnterWater(chip, status, action, duration=7): pure_valve_status = 2
# if action == 'On': elif action == 'On' and duration < 7:
# status[4] = 1 pure_valve_status = 1
# else: # action == 'Off' else:
# status[4] = 0 pure_valve_status = 0
# chip.set_values(status)
global main_valve_status
status[5] = 0
status[6] = 0
chip.set_values(status)
time.sleep(0.05)
if main_valve_status != 0 and action == 'Off': def Valve_EnterWater(chip, status, action):
status[5] = 0
status[6] = 1
chip.set_values(status)
time.sleep(7)
main_valve_status = 0
elif main_valve_status == 0 and action == 'On':
status[5] = 1
status[6] = 0
chip.set_values(status)
time.sleep(duration)
if duration >= 7:
main_valve_status = 2
elif duration < 7:
main_valve_status = 1
status[5] = 0
status[6] = 0
chip.set_values(status)
time.sleep(0.05)
# def Valve_MainWater(chip, status, action, duration=7):
def Valve_MainWater(chip, status, action):
global main_valve_status
# status[5] = 0
# status[6] = 0
# chip.set_values(status)
# time.sleep(0.05)
# if main_valve_status != 0 and action == 'Off':
# status[5] = 0
# status[6] = 1
# chip.set_values(status)
# time.sleep(7)
# main_valve_status = 0
# elif main_valve_status == 0 and action == 'On':
# status[5] = 1
# status[6] = 0
# chip.set_values(status)
# time.sleep(duration)
# if duration >= 7:
# main_valve_status = 2
# elif duration < 7:
# main_valve_status = 1
# status[5] = 0
# status[6] = 0
# chip.set_values(status)
# time.sleep(0.05)
if action == 'On': if action == 'On':
status[4] = 1 status[4] = 1
else: # action == 'Off' else: # action == 'Off'
@ -138,6 +75,38 @@ def Valve_MainWater(chip, status, action):
chip.set_values(status) chip.set_values(status)
def Valve_MainWater(chip, status, action, duration=7):
global main_valve_status
status[5] = 0
status[6] = 0
chip.set_values(status)
time.sleep(0.05)
if action == 'On':
status[5] = 1
status[6] = 0
chip.set_values(status)
time.sleep(duration)
else: # 'Off'
if main_valve_status != 0:
status[5] = 0
status[6] = 1
chip.set_values(status)
time.sleep(7)
status[5] = 0
status[6] = 0
chip.set_values(status)
time.sleep(0.05)
if action == 'On' and duration >= 7:
main_valve_status = 2
elif action == 'On' and duration < 7:
main_valve_status = 1
else:
main_valve_status = 0
def Measure_Weight(client): def Measure_Weight(client):
# print('in') # print('in')
val = 0 val = 0
@ -162,13 +131,12 @@ def Calculate_Concentration(weight):
result = (float(weight) * volume_water * 128.5) - 126.11 # 1000 / 531 = 1.883239171 result = (float(weight) * volume_water * 128.5) - 126.11 # 1000 / 531 = 1.883239171
data['data']['concentration'] = result data['data']['concentration'] = result
# print(f'{weight}, {result}') # print(f'{weight}, {result}')
return result
def Set_Zero(client): def Set_Zero(client):
client.write_coil(1, 1) client.write_coil(1, 1)
def Command_Read(): def Command_Read():
global client, main_valve_status, logger global client, main_valve_status
with open('./control.json', 'r') as f: with open('./control.json', 'r') as f:
cmd = json.load(f) cmd = json.load(f)
@ -176,103 +144,95 @@ def Command_Read():
if cmd['type'] == 'auto': if cmd['type'] == 'auto':
main_duration = float(cmd['device']['main']['duration']) main_duration = float(cmd['device']['main']['duration'])
pure_duration = float(cmd['device']['pure']['duration']) pure_duration = float(cmd['device']['pure']['duration'])
step0_duration = float(cmd['working-time']['step0']) setp0_duration = float(cmd['working-time']['setp0'])
step1_duration = float(cmd['working-time']['step1']) setp1_duration = float(cmd['working-time']['setp1'])
step2_duration = float(cmd['working-time']['step2']) setp2_duration = float(cmd['working-time']['setp2'])
step3_duration = float(cmd['working-time']['step3']) setp3_duration = float(cmd['working-time']['setp3'])
step4_duration = float(cmd['working-time']['step4']) setp4_duration = float(cmd['working-time']['setp4'])
step5_duration = float(cmd['working-time']['step5']) setp5_duration = float(cmd['working-time']['setp5'])
step6_duration = float(cmd['working-time']['step6']) setp6_duration = float(cmd['working-time']['setp6'])
step7_duration = float(cmd['working-time']['step7']) setp7_duration = float(cmd['working-time']['setp7'])
step8_duration = float(cmd['working-time']['step8']) setp8_duration = float(cmd['working-time']['setp8'])
step9_duration = float(cmd['working-time']['step9']) setp9_duration = float(cmd['working-time']['setp9'])
# Step 0. Mesure init weight before starting the sequence # Step 0. Mesure init weight before starting the sequence
time.sleep(step0_duration) time.sleep(setp0_duration)
start = Measure_Weight(client=client) start = Measure_Weight(client=client)
# Step 1. Vent pured water before input mixed water # Step 1. Vent pured water before input mixed water
# Target valve status: [Motor: Off, Vent: On, Pure: Off, Enter: On, Main: On] # Target valve status: [Motor: Off, Vent: On, Pure: Off, Enter: On, Main: On]
# Valve_EnterWater(chip=output_lines, status=status, action='On') Valve_EnterWater(chip=output_lines, status=status, action='On')
Valve_MainWater(chip=output_lines, status=status, action='On')
time.sleep(0.5) time.sleep(0.5)
Valve_Vent(chip=output_lines, status=status, action='On') Valve_Vent(chip=output_lines, status=status, action='On')
time.sleep(0.5) time.sleep(0.5)
# Valve_MainWater(chip=output_lines, status=status, action='On', duration=main_duration) Valve_MainWater(chip=output_lines, status=status, action='On', duration=main_duration)
Valve_EnterWater(chip=output_lines, status=status, action='On', duration=main_duration) time.sleep(setp1_duration)
time.sleep(step1_duration)
# Step 2. Empty the remaining pure water # Step 2. Empty the remaining pure water
# Target valve status: [Motor: Off, Vent: On, Pure: Off, Enter: Off, Main: On] # Target valve status: [Motor: Off, Vent: On, Pure: Off, Enter: Off, Main: On]
Valve_EnterWater(chip=output_lines, status=status, action='Off') Valve_EnterWater(chip=output_lines, status=status, action='Off')
time.sleep(step2_duration) time.sleep(setp2_duration)
# Step 3. Input the mixed water # Step 3. Input the mixed water
# Target valve status: [Motor: Off, Vent: Off, Pure: Off, Enter: On, Main: On] # Target valve status: [Motor: Off, Vent: Off, Pure: Off, Enter: On, Main: On]
Valve_Vent(chip=output_lines, status=status, action='Off') Valve_Vent(chip=output_lines, status=status, action='Off')
time.sleep(0.5) time.sleep(0.5)
# Valve_EnterWater(chip=output_lines, status=status, action='On') Valve_EnterWater(chip=output_lines, status=status, action='On')
Valve_EnterWater(chip=output_lines, status=status, action='On', duration=main_duration) time.sleep(setp3_duration)
time.sleep(step3_duration)
# Step 4. Mesure the weight # Step 4. Mesure the weight
# Target valve status: [Motor: Off, Vent: Off, Pure: Off, Enter: Off, Main: Off] # Target valve status: [Motor: Off, Vent: Off, Pure: Off, Enter: Off, Main: Off]
Valve_MainWater(chip=output_lines, status=status, action='Off')
time.sleep(0.5)
Valve_EnterWater(chip=output_lines, status=status, action='Off') Valve_EnterWater(chip=output_lines, status=status, action='Off')
time.sleep(step4_duration) time.sleep(0.5)
Valve_MainWater(chip=output_lines, status=status, action='Off')
time.sleep(setp4_duration)
end = Measure_Weight(client=client) end = Measure_Weight(client=client)
time.sleep(1) time.sleep(1)
res = Calculate_Concentration(weight=(float(end)-float(start))) Calculate_Concentration(weight=(float(end)-float(start)))
logger.debug(f'[auto] weight: {end - start} concentration: {res:.3f}')
# Step 5. Drain the mixed water and add pure water. # Step 5. Drain the mixed water and add pure water.
# Target valve status: [Motor: Off, Vent: On, Pure: On, Enter: On, Main: Off] # Target valve status: [Motor: Off, Vent: On, Pure: On, Enter: On, Main: Off]
Valve_Vent(chip=output_lines, status=status, action='On')
time.sleep(0.5)
Valve_EnterWater(chip=output_lines, status=status, action='On') Valve_EnterWater(chip=output_lines, status=status, action='On')
time.sleep(0.5) time.sleep(0.5)
# Valve_PureWater(chip=output_lines, status=status, action='On', duration=pure_duration) Valve_Vent(chip=output_lines, status=status, action='On')
Valve_PureWater(chip=output_lines, status=status, action='On') time.sleep(0.5)
time.sleep(step5_duration) Valve_PureWater(chip=output_lines, status=status, action='On', duration=pure_duration)
time.sleep(setp5_duration)
# Step 6. Drain mixed water # Step 6. Drain mixed water
# Target valve status: [Motor: Off, Vent: On, Pure: On, Enter: Off, Main: Off] # Target valve status: [Motor: Off, Vent: On, Pure: On, Enter: Off, Main: Off]
Valve_EnterWater(chip=output_lines, status=status, action='Off') Valve_EnterWater(chip=output_lines, status=status, action='Off')
time.sleep(step6_duration) time.sleep(setp6_duration)
# Step 7. Input pure water and clean # Step 7. Input pure water and clean
# Target valve status: [Motor: On, Vent: Off, Pure: On, Enter: On, Main: Off] # Target valve status: [Motor: On, Vent: Off, Pure: On, Enter: On, Main: Off]
Valve_Vent(chip=output_lines, status=status, action='Off')
time.sleep(0.5)
Valve_EnterWater(chip=output_lines, status=status, action='On') Valve_EnterWater(chip=output_lines, status=status, action='On')
time.sleep(0.5) time.sleep(0.5)
Valve_Vent(chip=output_lines, status=status, action='Off')
time.sleep(0.5)
Motor(chip=output_lines, status=status, action='On') Motor(chip=output_lines, status=status, action='On')
time.sleep(step7_duration) time.sleep(setp7_duration)
# Step 8. Drain pure Water # Step 8. Drain pure Water
# Target valve status: [Motor: On, Vent: On, Pure: Off, Enter: Off, Main: Off] # Target valve status: [Motor: On, Vent: On, Pure: Off, Enter: Off, Main: Off]
Valve_Vent(chip=output_lines, status=status, action='On')
time.sleep(0.5)
Valve_EnterWater(chip=output_lines, status=status, action='Off') Valve_EnterWater(chip=output_lines, status=status, action='Off')
time.sleep(0.5) time.sleep(0.5)
Valve_Vent(chip=output_lines, status=status, action='On')
time.sleep(0.5)
Valve_PureWater(chip=output_lines, status=status, action='Off') Valve_PureWater(chip=output_lines, status=status, action='Off')
time.sleep(step8_duration) time.sleep(setp8_duration)
# Step 9. Stop moter # Step 9. Stop moter
# Target valve status: [Motor: Off, Vent: On, Pure: Off, Enter: Off, Main: Off] # Target valve status: [Motor: Off, Vent: On, Pure: Off, Enter: Off, Main: Off]
Motor(chip=output_lines, status=status, action='Off') Motor(chip=output_lines, status=status, action='Off')
time.sleep(step9_duration) time.sleep(setp9_duration)
return 1 return 1
elif cmd['type'] == 'clean': elif cmd['type'] == 'clean':
logger.debug(f"[clean] duration: {int(cmd['maintenance']['clean']['duration'])}")
clean_system() clean_system()
time.sleep(3) time.sleep(3)
@ -281,25 +241,20 @@ def Command_Read():
Valve_Vent(chip=output_lines, status=status, action=cmd['device']['vent']['action']) Valve_Vent(chip=output_lines, status=status, action=cmd['device']['vent']['action'])
# Valve_MixedWater(chip=output_lines, status=status, action=cmd['device']['mixed']['action']) # Valve_MixedWater(chip=output_lines, status=status, action=cmd['device']['mixed']['action'])
# Valve_PureWater(chip=output_lines, status=status, action=cmd['device']['pure']['action']) # Valve_PureWater(chip=output_lines, status=status, action=cmd['device']['pure']['action'])
# Valve_EnterWater(chip=output_lines, status=status, action=cmd['device']['enter']['action']) Valve_EnterWater(chip=output_lines, status=status, action=cmd['device']['enter']['action'])
Valve_MainWater(chip=output_lines, status=status, action=cmd['device']['main']['action'])
if cmd['device']['pure']['duration'] == 0: if cmd['device']['pure']['duration'] == 0:
Valve_PureWater(chip=output_lines, status=status, action=cmd['device']['pure']['action']) Valve_PureWater(chip=output_lines, status=status, action=cmd['device']['pure']['action'])
else: else:
Valve_PureWater(chip=output_lines, status=status, action=cmd['device']['pure']['action'], duration=cmd['device']['pure']['duration']) Valve_PureWater(chip=output_lines, status=status, action=cmd['device']['pure']['action'], duration=cmd['device']['pure']['duration'])
# if cmd['device']['main']['duration'] == 0:
# Valve_MainWater(chip=output_lines, status=status, action=cmd['device']['main']['action'])
# else:
# Valve_MainWater(chip=output_lines, status=status, action=cmd['device']['main']['action'], duration=cmd['device']['main']['duration'])
if cmd['device']['main']['duration'] == 0: if cmd['device']['main']['duration'] == 0:
Valve_EnterWater(chip=output_lines, status=status, action=cmd['device']['enter']['action']) Valve_MainWater(chip=output_lines, status=status, action=cmd['device']['main']['action'])
else: else:
Valve_EnterWater(chip=output_lines, status=status, action=cmd['device']['enter']['action'], duration=cmd['device']['main']['duration']) Valve_MainWater(chip=output_lines, status=status, action=cmd['device']['main']['action'], duration=cmd['device']['main']['duration'])
if cmd['device']['measure']['action'] == 'On': if cmd['device']['measure']['action'] == 'On':
result = Measure_Weight(client=client) result = Measure_Weight(client=client)
Calculate_Concentration(result) Calculate_Concentration(result)
@ -324,22 +279,16 @@ def clean_system():
Valve_MainWater(chip=output_lines, status=status, action='On') Valve_MainWater(chip=output_lines, status=status, action='On')
time.sleep(0.5) time.sleep(0.5)
Valve_PureWater(chip=output_lines, status=status, action='On') Valve_PureWater(chip=output_lines, status=status, action='On')
time.sleep(0.5)
Valve_MixedWater(chip=output_lines, status=status, action='On')
time.sleep(clean_duration) time.sleep(clean_duration)
Valve_MainWater(chip=output_lines, status=status, action='Off') Valve_MainWater(chip=output_lines, status=status, action='Off')
time.sleep(0.5) time.sleep(0.5)
Valve_EnterWater(chip=output_lines, status=status, action='On')
time.sleep(0.5)
Valve_Vent(chip=output_lines, status=status, action='On')
time.sleep(clean_duration)
Valve_PureWater(chip=output_lines, status=status, action='Off') Valve_PureWater(chip=output_lines, status=status, action='Off')
time.sleep(0.5) time.sleep(0.5)
Valve_Vent(chip=output_lines, status=status, action='Off') Valve_MixedWater(chip=output_lines, status=status, action='Off')
time.sleep(0.5) time.sleep(6)
Valve_EnterWater(chip=output_lines, status=status, action='Off')
time.sleep(0.5)
def runAction(): def runAction():
# Write the app's actions in the "runAction" function. # Write the app's actions in the "runAction" function.
@ -402,7 +351,7 @@ def runAction():
time.sleep(3 - diff) time.sleep(3 - diff)
def handle_client(conn, ip, port): def handle_client(conn, ip, port):
global data, logger global data
while True: while True:
try: try:
recv = conn.recv(100) recv = conn.recv(100)
@ -425,8 +374,6 @@ def handle_client(conn, ip, port):
data_weight = '{:.3f}'.format(h_weight) data_weight = '{:.3f}'.format(h_weight)
data_concent = '{:.3f}'.format(h_concentration) data_concent = '{:.3f}'.format(h_concentration)
logger.debug(f'TCP [R:Transfer data] weight: {data_weight}, concent: {data_concent}')
send_msg = 'STX' + time_str + '|' + data_weight + '|' + data_concent + 'ETX' send_msg = 'STX' + time_str + '|' + data_weight + '|' + data_concent + 'ETX'
try: try:
@ -444,7 +391,6 @@ def handle_client(conn, ip, port):
conn.sendall(err_msg.encode("utf8")) conn.sendall(err_msg.encode("utf8"))
elif message[3] == 'S': # Start measurement elif message[3] == 'S': # Start measurement
logger.debug(f'TCP [S:Start measurement]')
try: try:
with open('./control.json', 'r') as f: with open('./control.json', 'r') as f:
cmd = json.load(f) cmd = json.load(f)
@ -461,7 +407,6 @@ def handle_client(conn, ip, port):
conn.sendall(err_msg.encode("utf8")) conn.sendall(err_msg.encode("utf8"))
elif message[3] == 'C': # Clean sequence elif message[3] == 'C': # Clean sequence
logger.debug(f'TCP [C:Clean sequence]')
try: try:
with open('./control.json', 'r') as f: with open('./control.json', 'r') as f:
cmd = json.load(f) cmd = json.load(f)
@ -478,7 +423,6 @@ def handle_client(conn, ip, port):
conn.sendall(err_msg.encode("utf8")) conn.sendall(err_msg.encode("utf8"))
elif message[3] == 'T': # Stop measurement elif message[3] == 'T': # Stop measurement
logger.debug(f'TCP [T:Stop measurement]')
try: try:
with open('./control.json', 'r') as f: with open('./control.json', 'r') as f:
cmd = json.load(f) cmd = json.load(f)
@ -527,11 +471,6 @@ def start_server(addr, port):
client_handler.start() client_handler.start()
soc.close() soc.close()
def seoul_time(*args):
utc_dt = datetime.now()
seoul_tz = pytz.timezone('Asia/Seoul')
return utc_dt.replace(tzinfo=pytz.utc).astimezone(seoul_tz).timetuple()
def exit_handler(signum, frame): def exit_handler(signum, frame):
Motor(chip=output_lines, status=status, action='Off') Motor(chip=output_lines, status=status, action='Off')
@ -546,7 +485,6 @@ def exit_handler(signum, frame):
sys.exit(0) sys.exit(0)
if __name__ == "__main__": if __name__ == "__main__":
# Set GPIO
output_chip = gpiod.chip('gpiochip11') output_chip = gpiod.chip('gpiochip11')
config = gpiod.line_request() config = gpiod.line_request()
config.consumer = 'output' config.consumer = 'output'
@ -557,40 +495,24 @@ if __name__ == "__main__":
status = [0, 0, 0, 0, 0, 0, 0, 0] status = [0, 0, 0, 0, 0, 0, 0, 0]
# When forced to terminate
signal.signal(signal.SIGINT, exit_handler) signal.signal(signal.SIGINT, exit_handler)
# Set the logger
logger = logging.getLogger('sampyo_dio')
logger.setLevel(logging.DEBUG)
handler = RotatingFileHandler('/home/root/working.log', maxBytes=1024*1024, backupCount=3)
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
formatter.converter = seoul_time
handler.setFormatter(formatter)
logger.addHandler(handler)
# Initialized valves
main_valve_status = 0 main_valve_status = 0
pure_valve_status = 0 pure_value_status = 0
Valve_MainWater(chip=output_lines, status=status, action='Off') Valve_MainWater(chip=output_lines, status=status, action='Off')
Valve_PureWater(chip=output_lines, status=status, action='Off') Valve_PureWater(chip=output_lines, status=status, action='Off')
# Read config file
with open('./config.json', encoding='UTF-8') as f: with open('./config.json', encoding='UTF-8') as f:
jsonData = json.load(f) jsonData = json.load(f)
# Set the weight of water in the chamber
volume_water = 1000.0 / float(jsonData['volume-water']) volume_water = 1000.0 / float(jsonData['volume-water'])
# Set the IP address and port of NodeQ RS-232 module and activate TCP Client
modbus_addr = jsonData['modbus-server']['address'] modbus_addr = jsonData['modbus-server']['address']
modbus_port = jsonData['modbus-server']['port'] modbus_port = jsonData['modbus-server']['port']
client = ModbusTcpClient(modbus_addr, modbus_port) client = ModbusTcpClient(modbus_addr, modbus_port)
# Define the default data format
data = { data = {
"timestamp": 0, "timestamp": 0,
"data":{ "data":{

View File