Compare commits

...

37 Commits

Author SHA1 Message Date
support.sampyo 61e7c3d4b7 Commit message 2024-10-10 07:53:25 +00:00
support.sampyo 5297824869 Commit message 2024-10-10 07:00:26 +00:00
support.sampyo 50a6bf2373 Commit message 2024-07-30 05:22:35 +00:00
support.sampyo 5c1d08ee98 Commit message 2024-07-30 04:55:55 +00:00
support.sampyo 95921c49b8 Commit message 2024-07-30 04:50:07 +00:00
support.sampyo 44c6a224c2 Commit message 2024-07-04 06:19:55 +00:00
support.sampyo 797816a6f5 Commit message 2024-07-04 06:14:16 +00:00
support.sampyo 5c41e0664d Commit message 2024-07-04 05:50:25 +00:00
support.sampyo f54f9e7fb5 Commit message 2024-07-04 05:45:11 +00:00
support.sampyo ad62a2f89e Commit message 2024-07-04 05:26:04 +00:00
support.sampyo c566b4070e Commit message 2024-07-04 05:12:08 +00:00
support.sampyo 4239597f8a Commit message 2024-06-12 05:25:29 +00:00
support.sampyo a47d7c2bd9 Commit message 2024-06-12 05:16:08 +00:00
support.sampyo 1a6344fccf Commit message 2024-05-31 01:41:55 +00:00
support.sampyo a493257c17 Commit message 2024-05-30 07:20:05 +00:00
support.sampyo 696cc6f0e8 Commit message 2024-05-30 06:37:40 +00:00
support.sampyo 02a44e8478 Commit message 2024-05-29 08:13:58 +00:00
support.sampyo 3fdb92ae4d Commit message 2024-05-29 08:11:32 +00:00
support.sampyo ddc05f15ee Commit message 2024-05-29 08:09:07 +00:00
support.sampyo 944013c835 Commit message 2024-05-29 06:42:52 +00:00
support.sampyo 8efbc66164 Commit message 2024-05-29 06:30:40 +00:00
support.sampyo d18653ef71 Commit message 2024-05-29 06:15:49 +00:00
support.sampyo 4328027519 Commit message 2024-05-29 06:03:54 +00:00
support.sampyo e5d745c4e1 Commit message 2024-05-29 05:51:51 +00:00
support.sampyo d1a2dd1027 Commit message 2024-05-29 04:27:22 +00:00
support.sampyo c1f26f9340 Commit message 2024-05-24 06:04:38 +00:00
support.sampyo 370d851500 Commit message 2024-05-24 05:17:25 +00:00
support.sampyo e1d1327849 Commit message 2024-05-23 07:15:58 +00:00
support.sampyo b0b16d396c Commit message 2024-05-23 07:09:27 +00:00
support.sampyo ae42726b4d Commit message 2024-05-23 07:03:51 +00:00
support.sampyo e99f5122cb Commit message 2024-05-23 06:47:31 +00:00
support.sampyo f5f155c1bc Commit message 2024-05-23 06:12:49 +00:00
support.sampyo 3a30bba1ef Commit message 2024-05-23 05:50:59 +00:00
support.sampyo 978b40a0c4 Commit message 2024-05-23 05:45:54 +00:00
support.sampyo 0c77a24a40 Commit message 2024-05-23 05:42:56 +00:00
support.sampyo 0a351ca635 Commit message 2024-05-23 05:33:27 +00:00
support.sampyo 0a996b5b66 Commit message 2024-05-23 01:32:45 +00:00
6 changed files with 683 additions and 394 deletions

BIN
.main.py.swp Normal file

Binary file not shown.

View File

@ -1,12 +1,12 @@
{ {
"appId": "81a695f0-a990-43c8-998f-2ba1bf9c6005", "appId": "81a695f0-a990-43c8-998f-2ba1bf9c6005",
"modbus-server": { "modbus-server": {
"address": "172.17.16.202", "address": "172.17.16.202",
"port": 5020 "port": 5020
}, },
"tcp-server": { "tcp-server": {
"address": "172.17.16.201", "address": "172.17.16.201",
"port": 24 "port": 24
}, },
"volume-water": 542 "volume-water": 542
} }

View File

@ -1,27 +1,49 @@
{ {
"device": { "device": {
"setzero": { "enter": {
"action": "Off" "action": "Off"
}, },
"measure": { "main": {
"action": "On", "action": "Off",
"duration": 20 "duration": 4
}, },
"mixed": { "measure": {
"action": "Off", "action": "On"
"duration": 15 },
}, "mixed": {
"pure": { "action": "Off"
"action": "Off", },
"duration": 15 "motor": {
}, "action": "Off"
"vent": { },
"action": "Off", "pure": {
"duration": 30 "action": "Off",
}, "duration": 4
"motor": { },
"action": "Off" "setzero": {
} "action": "Off"
}, },
"type": "manual" "vent": {
} "action": "Off"
}
},
"maintenance": {
"clean": {
"duration": 20,
"time": 25
}
},
"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

@ -1,11 +1,11 @@
version: bwc/v2 # bwc 버전 정보입니다. version: bwc/v2 # bwc 버전 정보입니다.
spec: spec:
appName: sampyo-dio-app # 앱의 이름입니다. appName: sampyo-dio-app # 앱의 이름입니다.
runFile: main.py # 앱의 실행 파일입니다. runFile: main.py # 앱의 실행 파일입니다.
env: env:
bin: python3 # 앱을 실행할 바이너라 파일 종류입니다.(장비에 따라 다르므로 확인 후 정의해야 합니다.) bin: python3 # 앱을 실행할 바이너라 파일 종류입니다.(장비에 따라 다르므로 확인 후 정의해야 합니다.)
virtualEnv: base # 사용할 가상환경 이름입니다. virtualEnv: base # 사용할 가상환경 이름입니다.
package: requirements.txt # 설치할 Python 패키지 정보 파일입니다.(기본 값은 requirement.txt 입니다.) package: requirements.txt # 설치할 Python 패키지 정보 파일입니다.(기본 값은 requirement.txt 입니다.)
stackbase: stackbase:
tagName: v0.0.14 # Stackbase(gitea)에 릴리즈 태그명 입니다. tagName: v0.0.51 # Stackbase(gitea)에 릴리즈 태그명 입니다.
repoName: sampyo-dio # Stackbase(gitea)에 저장될 저장소 이릅니다. repoName: sampyo-dio # Stackbase(gitea)에 저장될 저장소 이릅니다.

955
main.py
View File

@ -1,344 +1,611 @@
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 # import AWSIoTPythonSDK.MQTTLib as AWSIoTPyMQTT
# import AWSIoTPythonSDK.MQTTLib as AWSIoTPyMQTT import sdtcloudnodeqmqtt
import sdtcloudnodeqmqtt import pytz
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):
if action == 'On': def Motor(chip, status, action):
status[0] = 1 if action == 'On':
else: # action == 'Off' status[0] = 1
status[0] = 0 else: # action == 'Off'
status[0] = 0
chip.set_values(status)
chip.set_values(status)
def Valve_Vent(chip, status, action):
if action == 'On': def Valve_Vent(chip, status, action):
status[1] = 1 if action == 'On':
else: # action == 'Off' status[1] = 1
status[1] = 0 else: # action == 'Off'
status[1] = 0
chip.set_values(status)
chip.set_values(status)
def Valve_MixedWater(chip, status, action):
if action == 'On': def Valve_MixedWater(chip, status, action):
status[2] = 1 if action == 'On':
else: # action == 'Off' status[2] = 1
status[2] = 0 else: # action == 'Off'
status[2] = 0
chip.set_values(status)
chip.set_values(status)
def Valve_PureWater(chip, status, action):
if action == 'On': def Valve_PureWater(chip, status, action, duration=7):
status[3] = 1 global pure_valve_status
else: # action == 'Off'
status[3] = 0 status[2] = 0
status[3] = 0
chip.set_values(status) chip.set_values(status)
time.sleep(0.05)
def Measure_Weight(client):
# print('In') if pure_valve_status != 0 and action == 'Off':
val = 0 status[2] = 0
try: status[3] = 1
result = client.read_holding_registers(1, 1) chip.set_values(status)
if result.isError(): time.sleep(7)
print(f'Error: {result}') pure_valve_status = 0
else: elif pure_valve_status == 0 and action == 'On':
val = result.registers[0] status[2] = 1
val -= 1000 status[3] = 0
val /= 1000 chip.set_values(status)
print(f'value: {val}') time.sleep(duration)
except Exception as e: if duration >= 7:
pass pure_valve_status = 2
elif duration < 7:
return val pure_valve_status = 1
def Calculate_Concentration(weight): status[2] = 0
global data, volume_water status[3] = 0
data['data']['weight'] = weight chip.set_values(status)
result = (float(weight) * volume_water * 128.5) - 126.11 # 1000 / 531 = 1.883239171 time.sleep(0.05)
data['data']['concentration'] = result
# print(f'{weight}, {result}') # def Valve_EnterWater(chip, status, action):
def Valve_EnterWater(chip, status, action, duration=7):
def Set_Zero(client): # if action == 'On':
client.write_coil(1, 1) # status[4] = 1
# else: # action == 'Off'
def Command_Read(): # status[4] = 0
with open('./control.json', 'r') as f:
cmd = json.load(f) # chip.set_values(status)
global main_valve_status
if cmd['type'] == 'auto':
status[5] = 0
Valve_Vent(chip=output_lines, status=status, action='Off') status[6] = 0
Motor(chip=output_lines, status=status, action='Off') chip.set_values(status)
time.sleep(0.05)
mixed_duration = int(cmd['device']['mixed']['duration'])
pure_duration = int(cmd['device']['pure']['duration']) if main_valve_status != 0 and action == 'Off':
vent_duration = int(cmd['device']['vent']['duration']) status[5] = 0
measure_duration = int(cmd['device']['vent']['duration']) status[6] = 1
chip.set_values(status)
time.sleep(5) time.sleep(7)
start = Measure_Weight(client=client) main_valve_status = 0
time.sleep(5) elif main_valve_status == 0 and action == 'On':
status[5] = 1
# input mixed water status[6] = 0
Valve_MixedWater(chip=output_lines, status=status, action='On') chip.set_values(status)
time.sleep(mixed_duration) time.sleep(duration)
Valve_MixedWater(chip=output_lines, status=status, action='Off') if duration >= 7:
time.sleep(measure_duration) main_valve_status = 2
elif duration < 7:
# measure weight main_valve_status = 1
end = Measure_Weight(client=client)
time.sleep(1) status[5] = 0
status[6] = 0
Calculate_Concentration(weight=(float(end)-float(start))) chip.set_values(status)
time.sleep(0.05)
# vent mixed water
Valve_Vent(chip=output_lines, status=status, action='On') # def Valve_MainWater(chip, status, action, duration=7):
time.sleep(0.5) def Valve_MainWater(chip, status, action):
Motor(chip=output_lines, status=status, action='On') global main_valve_status
time.sleep(vent_duration)
Motor(chip=output_lines, status=status, action='Off') # status[5] = 0
time.sleep(0.5) # status[6] = 0
Valve_Vent(chip=output_lines, status=status, action='Off') # chip.set_values(status)
time.sleep(0.5) # time.sleep(0.05)
# input pure water # if main_valve_status != 0 and action == 'Off':
Valve_PureWater(chip=output_lines, status=status, action='On') # status[5] = 0
time.sleep(pure_duration) # status[6] = 1
Valve_PureWater(chip=output_lines, status=status, action='Off') # chip.set_values(status)
time.sleep(0.5) # time.sleep(7)
# main_valve_status = 0
# vent pure water # elif main_valve_status == 0 and action == 'On':
Valve_Vent(chip=output_lines, status=status, action='On') # status[5] = 1
time.sleep(0.5) # status[6] = 0
Motor(chip=output_lines, status=status, action='On') # chip.set_values(status)
time.sleep(vent_duration) # time.sleep(duration)
Motor(chip=output_lines, status=status, action='Off') # if duration >= 7:
time.sleep(0.5) # main_valve_status = 2
Valve_Vent(chip=output_lines, status=status, action='Off') # elif duration < 7:
time.sleep(1) # main_valve_status = 1
return 1 # status[5] = 0
# status[6] = 0
else: # cmd['type'] == 'manual' # chip.set_values(status)
Motor(chip=output_lines, status=status, action=cmd['device']['motor']['action']) # time.sleep(0.05)
Valve_Vent(chip=output_lines, status=status, action=cmd['device']['vent']['action'])
Valve_MixedWater(chip=output_lines, status=status, action=cmd['device']['mixed']['action']) if action == 'On':
Valve_PureWater(chip=output_lines, status=status, action=cmd['device']['pure']['action']) status[4] = 1
if cmd['device']['measure']['action'] == 'On': else: # action == 'Off'
result = Measure_Weight(client=client) status[4] = 0
Calculate_Concentration(result)
return 1 chip.set_values(status)
if cmd['device']['setzero']['action'] == 'On': def Measure_Weight(client):
Set_Zero(client=client) # print('in')
val = 0
return 0 try:
result = client.read_holding_registers(1, 1)
def runAction(): if not result:
# Write the app's actions in the "runAction" function. print(f'Error: {result}')
else:
# Connect MQTT Broker val = result.registers[0]
# You have to rename client id. There are special rules. val -= 1000
# Client Name: "device-app-*" val /= 1000
# For Example # print(f'value: {val}')
# 1. device-app-test -> Good except Exception as e:
# 2. device-app-light-app -> Good print(f'Measure_Weight Error: {e}')
# 3. device-test-app -> Bad pass
sdtcloud = sdtcloudnodeqmqtt.sdtcloudnodeqmqtt()
mqttClient1 = sdtcloud.setClient(f"device-app-1{uuid.uuid1()}") # parameter is client ID(string) return float(val)
mqttClient2 = sdtcloud.setClient(f"device-app-2{uuid.uuid1()}") # parameter is client ID(string)
mqttClient3 = sdtcloud.setClient(f"device-app-3{uuid.uuid1()}") # parameter is client ID(string) def Calculate_Concentration(weight):
mqttClient4 = sdtcloud.setClient(f"device-app-4{uuid.uuid1()}") # parameter is client ID(string) global data, volume_water
mqttClient5 = sdtcloud.setClient(f"device-app-5{uuid.uuid1()}") # parameter is client ID(string) data['data']['weight'] = weight
mqttlist = [mqttClient1, mqttClient2, mqttClient3, mqttClient4, mqttClient5] result = (float(weight) * volume_water * 128.5) - 126.11 # 1000 / 531 = 1.883239171
data['data']['concentration'] = result
# If you have config's value, please make config.json file. # print(f'{weight}, {result}')
# - Project Code's variable: projectCode(string) return result
# - Asset Code's variable: assetCode(string)
# - You may need it to create a topic. def Set_Zero(client):
client.write_coil(1, 1)
cnt = 0 def Command_Read():
while True: global client, main_valve_status, logger
start = time.time()
result = Command_Read() with open('./control.json', 'r') as f:
cmd = json.load(f)
if result:
data['timestamp'] = int(time.time() * 1000) if cmd['type'] == 'auto':
sdtcloud.pubMessage(mqttlist[cnt], data) main_duration = float(cmd['device']['main']['duration'])
cnt += 1 pure_duration = float(cmd['device']['pure']['duration'])
if cnt == 5: step0_duration = float(cmd['working-time']['step0'])
cnt = 0 step1_duration = float(cmd['working-time']['step1'])
step2_duration = float(cmd['working-time']['step2'])
end = time.time() step3_duration = float(cmd['working-time']['step3'])
step4_duration = float(cmd['working-time']['step4'])
diff = end - start step5_duration = float(cmd['working-time']['step5'])
if diff < 3: step6_duration = float(cmd['working-time']['step6'])
time.sleep(3 - diff) step7_duration = float(cmd['working-time']['step7'])
step8_duration = float(cmd['working-time']['step8'])
def handle_client(conn, ip, port): step9_duration = float(cmd['working-time']['step9'])
global data
while True:
try: # Step 0. Mesure init weight before starting the sequence
recv = conn.recv(100) time.sleep(step0_duration)
if not recv: start = Measure_Weight(client=client)
# print(f"Connection with {addr} was reset. Waiting for new connection.")
break # Step 1. Vent pured water before input mixed water
# Target valve status: [Motor: Off, Vent: On, Pure: Off, Enter: On, Main: On]
message = recv.decode().strip() # Valve_EnterWater(chip=output_lines, status=status, action='On')
Valve_MainWater(chip=output_lines, status=status, action='On')
if message[:3] != 'STX' or message[-3:] != 'ETX': time.sleep(0.5)
err_msg = 'STXERRORETX' Valve_Vent(chip=output_lines, status=status, action='On')
conn.sendall(err_msg.encode("utf8")) time.sleep(0.5)
else: # Valve_MainWater(chip=output_lines, status=status, action='On', duration=main_duration)
if message[3] == 'R': # Transfer data from SDT to Sampyo Valve_EnterWater(chip=output_lines, status=status, action='On', duration=main_duration)
now = datetime.now(pytz.timezone('Asia/Seoul')) time.sleep(step1_duration)
time_str = now.strftime('%Y%m%d%H%M%S')
# Step 2. Empty the remaining pure water
h_weight = float(data['data']['weight']) # Target valve status: [Motor: Off, Vent: On, Pure: Off, Enter: Off, Main: On]
h_concentration = float(data['data']['concentration']) Valve_EnterWater(chip=output_lines, status=status, action='Off')
data_weight = '{:.3f}'.format(h_weight) time.sleep(step2_duration)
data_concent = '{:.3f}'.format(h_concentration)
# Step 3. Input the mixed water
send_msg = 'STX' + time_str + '|' + data_weight + '|' + data_concent + 'ETX' # Target valve status: [Motor: Off, Vent: Off, Pure: Off, Enter: On, Main: On]
Valve_Vent(chip=output_lines, status=status, action='Off')
try: time.sleep(0.5)
with open('./control.json', 'r') as f: # Valve_EnterWater(chip=output_lines, status=status, action='On')
cmd = json.load(f) Valve_EnterWater(chip=output_lines, status=status, action='On', duration=main_duration)
time.sleep(step3_duration)
cmd['device']['measure']['action'] = 'On'
# Step 4. Mesure the weight
with open('./control.json', 'w') as f: # Target valve status: [Motor: Off, Vent: Off, Pure: Off, Enter: Off, Main: Off]
json.dump(cmd, f, indent=4) Valve_MainWater(chip=output_lines, status=status, action='Off')
time.sleep(0.5)
conn.sendall(send_msg.encode("utf8")) Valve_EnterWater(chip=output_lines, status=status, action='Off')
except Exception as e: time.sleep(step4_duration)
err_msg = 'STXERRORETX'
conn.sendall(err_msg.encode("utf8"))
end = Measure_Weight(client=client)
elif message[3] == 'S': # Start measurement time.sleep(1)
try:
with open('./control.json', 'r') as f: res = Calculate_Concentration(weight=(float(end)-float(start)))
cmd = json.load(f)
logger.debug(f'[auto] weight: {end - start} concentration: {res:.3f}')
cmd['type'] = 'auto'
# Step 5. Drain the mixed water and add pure water.
with open('./control.json', 'w') as f: # Target valve status: [Motor: Off, Vent: On, Pure: On, Enter: On, Main: Off]
json.dump(cmd, f, indent=4) Valve_Vent(chip=output_lines, status=status, action='On')
time.sleep(0.5)
send_msg = 'STXOKETX' Valve_EnterWater(chip=output_lines, status=status, action='On')
conn.sendall(send_msg.encode("utf8")) time.sleep(0.5)
except Exception as e: # Valve_PureWater(chip=output_lines, status=status, action='On', duration=pure_duration)
err_msg = 'STXERRORETX' Valve_PureWater(chip=output_lines, status=status, action='On')
conn.sendall(err_msg.encode("utf8")) time.sleep(step5_duration)
elif message[3] == 'T': # Stop measurement # Step 6. Drain mixed water
try: # Target valve status: [Motor: Off, Vent: On, Pure: On, Enter: Off, Main: Off]
with open('./control.json', 'r') as f: Valve_EnterWater(chip=output_lines, status=status, action='Off')
cmd = json.load(f) time.sleep(step6_duration)
cmd['type'] = 'manual' # Step 7. Input pure water and clean
cmd['device']['measure']['action'] = 'Off' # Target valve status: [Motor: On, Vent: Off, Pure: On, Enter: On, Main: Off]
Valve_Vent(chip=output_lines, status=status, action='Off')
with open('./control.json', 'w') as f: time.sleep(0.5)
json.dump(cmd, f, indent=4) Valve_EnterWater(chip=output_lines, status=status, action='On')
time.sleep(0.5)
send_msg = 'STXOKETX' Motor(chip=output_lines, status=status, action='On')
conn.sendall(send_msg.encode("utf8")) time.sleep(step7_duration)
except Exception as e:
err_msg = 'STXERRORETX' # Step 8. Drain pure Water
conn.sendall(err_msg.encode("utf8")) # Target valve status: [Motor: On, Vent: On, Pure: Off, Enter: Off, Main: Off]
Valve_Vent(chip=output_lines, status=status, action='On')
else: time.sleep(0.5)
err_msg = 'STXERRORETX' Valve_EnterWater(chip=output_lines, status=status, action='Off')
conn.sendall(err_msg.encode("utf8")) time.sleep(0.5)
except ConnectionResetError: Valve_PureWater(chip=output_lines, status=status, action='Off')
# print("Connection with " + ip + ":" + port + " was reset. Waiting for new connection.") time.sleep(step8_duration)
break
# Step 9. Stop moter
# print("Closing the connection") # Target valve status: [Motor: Off, Vent: On, Pure: Off, Enter: Off, Main: Off]
Motor(chip=output_lines, status=status, action='Off')
def start_server(addr, port): time.sleep(step9_duration)
host = addr # "25.7.57.1"
port = port # 5000 return 1
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) elif cmd['type'] == 'clean':
soc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) logger.debug(f"[clean] duration: {int(cmd['maintenance']['clean']['duration'])}")
clean_system()
try: time.sleep(3)
soc.bind((host, port))
except: else: # cmd['type'] == 'manual'
sys.exit() Motor(chip=output_lines, status=status, action=cmd['device']['motor']['action'])
Valve_Vent(chip=output_lines, status=status, action=cmd['device']['vent']['action'])
soc.listen(1) # Only one connection at a time. # Valve_MixedWater(chip=output_lines, status=status, action=cmd['device']['mixed']['action'])
# Valve_PureWater(chip=output_lines, status=status, action=cmd['device']['pure']['action'])
while True: # Valve_EnterWater(chip=output_lines, status=status, action=cmd['device']['enter']['action'])
conn, addr = soc.accept() Valve_MainWater(chip=output_lines, status=status, action=cmd['device']['main']['action'])
ip, port = str(addr[0]), str(addr[1])
print("Connected with " + ip + ":" + port) if cmd['device']['pure']['duration'] == 0:
Valve_PureWater(chip=output_lines, status=status, action=cmd['device']['pure']['action'])
client_handler = threading.Thread(target=handle_client, args=(conn, ip, port)) else:
client_handler.start() Valve_PureWater(chip=output_lines, status=status, action=cmd['device']['pure']['action'], duration=cmd['device']['pure']['duration'])
soc.close() # if cmd['device']['main']['duration'] == 0:
# Valve_MainWater(chip=output_lines, status=status, action=cmd['device']['main']['action'])
def exit_handler(signum, frame): # else:
Motor(chip=output_lines, status=status, action='Off') # Valve_MainWater(chip=output_lines, status=status, action=cmd['device']['main']['action'], duration=cmd['device']['main']['duration'])
Valve_Vent(chip=output_lines, status=status, action='Off')
Valve_MixedWater(chip=output_lines, status=status, action='Off') if cmd['device']['main']['duration'] == 0:
Valve_PureWater(chip=output_lines, status=status, action='Off') Valve_EnterWater(chip=output_lines, status=status, action=cmd['device']['enter']['action'])
else:
client.close() Valve_EnterWater(chip=output_lines, status=status, action=cmd['device']['enter']['action'], duration=cmd['device']['main']['duration'])
sys.exit(0)
if cmd['device']['measure']['action'] == 'On':
if __name__ == "__main__": result = Measure_Weight(client=client)
output_chip = gpiod.chip('gpiochip11') Calculate_Concentration(result)
config = gpiod.line_request() return 1
config.consumer = 'output'
config.request_type = gpiod.line_request.DIRECTION_OUTPUT if cmd['device']['setzero']['action'] == 'On':
Set_Zero(client=client)
output_lines = output_chip.get_lines([0, 1, 2, 3, 4, 5, 6, 7])
output_lines.request(config, default_vals=[0, 0, 0, 0, 0, 0, 0, 0]) return 0
status = [0, 0, 0, 0, 0, 0, 0, 0] def clean_system():
global main_valve_status
signal.signal(signal.SIGINT, exit_handler) with open('./control.json', 'r') as f:
cmd = json.load(f)
with open('./config.json', encoding='UTF-8') as f:
jsonData = json.load(f) clean_duration = int(cmd['maintenance']['clean']['duration'])
volume_water = 1000.0 / float(jsonData['volume-water']) if cmd['type'] == 'clean':
Valve_EnterWater(chip=output_lines, status=status, action='Off')
modbus_addr = jsonData['modbus-server']['address'] time.sleep(0.5)
modbus_port = jsonData['modbus-server']['port']
Valve_MainWater(chip=output_lines, status=status, action='On')
client = ModbusTcpClient(modbus_addr, modbus_port) time.sleep(0.5)
Valve_PureWater(chip=output_lines, status=status, action='On')
data = { time.sleep(clean_duration)
"timestamp": 0,
"data":{ Valve_MainWater(chip=output_lines, status=status, action='Off')
"weight": 0, time.sleep(0.5)
"concentration": 0
} Valve_EnterWater(chip=output_lines, status=status, action='On')
} time.sleep(0.5)
Valve_Vent(chip=output_lines, status=status, action='On')
## Get ProjectCode and AssetCode time.sleep(clean_duration)
## Execution main funcion Valve_PureWater(chip=output_lines, status=status, action='Off')
operation_thread = threading.Thread(target=runAction, args=()) time.sleep(0.5)
operation_thread.start() Valve_Vent(chip=output_lines, status=status, action='Off')
time.sleep(0.5)
tcp_addr = jsonData['tcp-server']['address'] Valve_EnterWater(chip=output_lines, status=status, action='Off')
tcp_port = jsonData['tcp-server']['port'] time.sleep(0.5)
## Execution TCP/IP server
start_server(addr=tcp_addr, port=tcp_port) def runAction():
# Write the app's actions in the "runAction" function.
# Connect MQTT Broker
# You have to rename client id. There are special rules.
# Client Name: "device-app-*"
# For Example
# 1. device-app-test -> Good
# 2. device-app-light-app -> Good
# 3. device-test-app -> Bad
global data
sdtcloud = sdtcloudnodeqmqtt.sdtcloudnodeqmqtt()
mqttClient1 = sdtcloud.setClient(f"device-app-1{uuid.uuid1()}") # parameter is client ID(string)
mqttClient2 = sdtcloud.setClient(f"device-app-2{uuid.uuid1()}") # parameter is client ID(string)
mqttClient3 = sdtcloud.setClient(f"device-app-3{uuid.uuid1()}") # parameter is client ID(string)
mqttClient4 = sdtcloud.setClient(f"device-app-4{uuid.uuid1()}") # parameter is client ID(string)
mqttClient5 = sdtcloud.setClient(f"device-app-5{uuid.uuid1()}") # parameter is client ID(string)
mqttlist = [mqttClient1, mqttClient2, mqttClient3, mqttClient4, mqttClient5]
# If you have config's value, please make config.json file.
# - Project Code's variable: projectCode(string)
# - Asset Code's variable: assetCode(string)
# - You may need it to create a topic.
cnt = 0
clean_flag = 0
while True:
start = time.time()
result = Command_Read()
if result:
data['timestamp'] = int(time.time() * 1000)
sdtcloud.pubMessage(mqttlist[cnt], data)
cnt += 1
if cnt == 5:
cnt = 0
end = time.time()
try:
now = datetime.now(pytz.timezone('Asia/Seoul'))
time_str = now.strftime('%H')
time_int = int(time_str)
with open('./control.json', 'r') as f:
cmd = json.load(f)
if time_int == int(cmd['maintenance']['clean']['time']):
if clean_flag < 3:
clean_flag += 1
clean_system()
else:
clean_flag = 0
except:
pass
diff = end - start
if diff < 3:
time.sleep(3 - diff)
def handle_client(conn, ip, port):
global data, logger
while True:
try:
recv = conn.recv(100)
if not recv:
# print(f"Connection with {addr} was reset. Waiting for new connection.")
break
message = recv.decode().strip()
if message[:3] != 'STX' or message[-3:] != 'ETX':
err_msg = 'STXERRORETX'
conn.sendall(err_msg.encode("utf8"))
else:
if message[3] == 'R': # Transfer data from SDT to Sampyo
now = datetime.now(pytz.timezone('Asia/Seoul'))
time_str = now.strftime('%Y%m%d%H%M%S')
h_weight = float(data['data']['weight'])
h_concentration = float(data['data']['concentration'])
data_weight = '{:.3f}'.format(h_weight)
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'
try:
with open('./control.json', 'r') as f:
cmd = json.load(f)
cmd['device']['measure']['action'] = 'On'
with open('./control.json', 'w') as f:
json.dump(cmd, f, indent=4)
conn.sendall(send_msg.encode("utf8"))
except Exception as e:
err_msg = 'STXERRORETX'
conn.sendall(err_msg.encode("utf8"))
elif message[3] == 'S': # Start measurement
logger.debug(f'TCP [S:Start measurement]')
try:
with open('./control.json', 'r') as f:
cmd = json.load(f)
cmd['type'] = 'auto'
with open('./control.json', 'w') as f:
json.dump(cmd, f, indent=4)
send_msg = 'STXOKETX'
conn.sendall(send_msg.encode("utf8"))
except Exception as e:
err_msg = 'STXERRORETX'
conn.sendall(err_msg.encode("utf8"))
elif message[3] == 'C': # Clean sequence
logger.debug(f'TCP [C:Clean sequence]')
try:
with open('./control.json', 'r') as f:
cmd = json.load(f)
cmd['type'] = 'clean'
with open('./control.json', 'w') as f:
json.dump(cmd, f, indent=4)
send_msg = 'STXOKETX'
conn.sendall(send_msg.encode("utf8"))
except Exception as e:
err_msg = 'STXERRORETX'
conn.sendall(err_msg.encode("utf8"))
elif message[3] == 'T': # Stop measurement
logger.debug(f'TCP [T:Stop measurement]')
try:
with open('./control.json', 'r') as f:
cmd = json.load(f)
cmd['type'] = 'manual'
cmd['device']['measure']['action'] = 'Off'
with open('./control.json', 'w') as f:
json.dump(cmd, f, indent=4)
send_msg = 'STXOKETX'
conn.sendall(send_msg.encode("utf8"))
except Exception as e:
err_msg = 'STXERRORETX'
conn.sendall(err_msg.encode("utf8"))
else:
err_msg = 'STXERRORETX'
conn.sendall(err_msg.encode("utf8"))
except ConnectionResetError:
# print("Connection with " + ip + ":" + port + " was reset. Waiting for new connection.")
break
# print("Closing the connection")
def start_server(addr, port):
host = addr # "172.17.16.201"
port = port # 5000
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
soc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
soc.bind((host, port))
except:
sys.exit()
soc.listen(1) # Only one connection at a time.
while True:
conn, addr = soc.accept()
ip, port = str(addr[0]), str(addr[1])
print("Connected with " + ip + ":" + port)
client_handler = threading.Thread(target=handle_client, args=(conn, ip, port))
client_handler.start()
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):
Motor(chip=output_lines, status=status, action='Off')
Valve_Vent(chip=output_lines, status=status, action='Off')
# Valve_MixedWater(chip=output_lines, status=status, action='Off')
Valve_PureWater(chip=output_lines, status=status, action='Off')
Valve_EnterWater(chip=output_lines, status=status, action='Off')
Valve_MainWater(chip=output_lines, status=status, action='Off')
client.close()
sys.exit(0)
if __name__ == "__main__":
# Set GPIO
output_chip = gpiod.chip('gpiochip11')
config = gpiod.line_request()
config.consumer = 'output'
config.request_type = gpiod.line_request.DIRECTION_OUTPUT
output_lines = output_chip.get_lines([0, 1, 2, 3, 4, 5, 6, 7])
output_lines.request(config, default_vals=[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)
# 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
pure_valve_status = 0
Valve_MainWater(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:
jsonData = json.load(f)
# Set the weight of water in the chamber
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_port = jsonData['modbus-server']['port']
client = ModbusTcpClient(modbus_addr, modbus_port)
# Define the default data format
data = {
"timestamp": 0,
"data":{
"weight": 0,
"concentration": 0
}
}
## Get ProjectCode and AssetCode
## Execution main funcion
operation_thread = threading.Thread(target=runAction, args=())
operation_thread.start()
tcp_addr = jsonData['tcp-server']['address']
tcp_port = jsonData['tcp-server']['port']
## Execution TCP/IP server
start_server(addr=tcp_addr, port=tcp_port)

0
working.log Normal file
View File