Compare commits
49 Commits
Author | SHA1 | Date |
---|---|---|
support.sampyo | 61e7c3d4b7 | |
support.sampyo | 5297824869 | |
support.sampyo | 50a6bf2373 | |
support.sampyo | 5c1d08ee98 | |
support.sampyo | 95921c49b8 | |
support.sampyo | 44c6a224c2 | |
support.sampyo | 797816a6f5 | |
support.sampyo | 5c41e0664d | |
support.sampyo | f54f9e7fb5 | |
support.sampyo | ad62a2f89e | |
support.sampyo | c566b4070e | |
support.sampyo | 4239597f8a | |
support.sampyo | a47d7c2bd9 | |
support.sampyo | 1a6344fccf | |
support.sampyo | a493257c17 | |
support.sampyo | 696cc6f0e8 | |
support.sampyo | 02a44e8478 | |
support.sampyo | 3fdb92ae4d | |
support.sampyo | ddc05f15ee | |
support.sampyo | 944013c835 | |
support.sampyo | 8efbc66164 | |
support.sampyo | d18653ef71 | |
support.sampyo | 4328027519 | |
support.sampyo | e5d745c4e1 | |
support.sampyo | d1a2dd1027 | |
support.sampyo | c1f26f9340 | |
support.sampyo | 370d851500 | |
support.sampyo | e1d1327849 | |
support.sampyo | b0b16d396c | |
support.sampyo | ae42726b4d | |
support.sampyo | e99f5122cb | |
support.sampyo | f5f155c1bc | |
support.sampyo | 3a30bba1ef | |
support.sampyo | 978b40a0c4 | |
support.sampyo | 0c77a24a40 | |
support.sampyo | 0a351ca635 | |
support.sampyo | 0a996b5b66 | |
support.sampyo | 237ec66789 | |
support.sampyo | 69dbc3b2e7 | |
support.sampyo | c35cd3e5e5 | |
support.sampyo | 1b38b348b5 | |
support.sampyo | 0cbfb8de48 | |
support.sampyo | ace959aee5 | |
support.sampyo | b204963582 | |
support.sampyo | febe5dcf33 | |
support.sampyo | 3bb08fbd7b | |
support.sampyo | 8510d04753 | |
support.sampyo | e4817279c7 | |
support.sampyo | 628dd66ca7 |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
12
config.json
12
config.json
|
@ -1,4 +1,12 @@
|
||||||
{
|
{
|
||||||
"KEY1": "VALUE1",
|
"appId": "81a695f0-a990-43c8-998f-2ba1bf9c6005",
|
||||||
"KEY2": "VALUE2"
|
"modbus-server": {
|
||||||
|
"address": "172.17.16.202",
|
||||||
|
"port": 5020
|
||||||
|
},
|
||||||
|
"tcp-server": {
|
||||||
|
"address": "172.17.16.201",
|
||||||
|
"port": 24
|
||||||
|
},
|
||||||
|
"volume-water": 542
|
||||||
}
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"appId": "81a695f0-a990-43c8-998f-2ba1bf9c6005",
|
||||||
|
"modbus-server": {
|
||||||
|
"address": "25.7.55.237",
|
||||||
|
"port": 5020
|
||||||
|
},
|
||||||
|
"tcp-server": {
|
||||||
|
"address": "25.7.57.1",
|
||||||
|
"port": 7007
|
||||||
|
},
|
||||||
|
"volume-water": 542
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
{
|
||||||
|
"device": {
|
||||||
|
"enter": {
|
||||||
|
"action": "Off"
|
||||||
|
},
|
||||||
|
"main": {
|
||||||
|
"action": "Off",
|
||||||
|
"duration": 4
|
||||||
|
},
|
||||||
|
"measure": {
|
||||||
|
"action": "On"
|
||||||
|
},
|
||||||
|
"mixed": {
|
||||||
|
"action": "Off"
|
||||||
|
},
|
||||||
|
"motor": {
|
||||||
|
"action": "Off"
|
||||||
|
},
|
||||||
|
"pure": {
|
||||||
|
"action": "Off",
|
||||||
|
"duration": 4
|
||||||
|
},
|
||||||
|
"setzero": {
|
||||||
|
"action": "Off"
|
||||||
|
},
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"device": {
|
||||||
|
"setzero": {
|
||||||
|
"action": "Off"
|
||||||
|
},
|
||||||
|
"measure": {
|
||||||
|
"action": "On"
|
||||||
|
},
|
||||||
|
"mixed": {
|
||||||
|
"action": "Off",
|
||||||
|
"duration": 15
|
||||||
|
},
|
||||||
|
"pure": {
|
||||||
|
"action": "Off",
|
||||||
|
"duration": 15
|
||||||
|
},
|
||||||
|
"vent": {
|
||||||
|
"action": "Off",
|
||||||
|
"duration": 30
|
||||||
|
},
|
||||||
|
"motor": {
|
||||||
|
"action":
|
||||||
|
"On"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "manual"
|
||||||
|
}
|
|
@ -5,7 +5,7 @@ spec:
|
||||||
env:
|
env:
|
||||||
bin: python3 # 앱을 실행할 바이너라 파일 종류입니다.(장비에 따라 다르므로 확인 후 정의해야 합니다.)
|
bin: python3 # 앱을 실행할 바이너라 파일 종류입니다.(장비에 따라 다르므로 확인 후 정의해야 합니다.)
|
||||||
virtualEnv: base # 사용할 가상환경 이름입니다.
|
virtualEnv: base # 사용할 가상환경 이름입니다.
|
||||||
package: requirement.txt # 설치할 Python 패키지 정보 파일입니다.(기본 값은 requirement.txt 입니다.)
|
package: requirements.txt # 설치할 Python 패키지 정보 파일입니다.(기본 값은 requirement.txt 입니다.)
|
||||||
stackbase:
|
stackbase:
|
||||||
tagName: v0.0.1 # Stackbase(gitea)에 릴리즈 태그명 입니다.
|
tagName: v0.0.51 # Stackbase(gitea)에 릴리즈 태그명 입니다.
|
||||||
repoName: sampyo-dio # Stackbase(gitea)에 저장될 저장소 이릅니다.
|
repoName: sampyo-dio # Stackbase(gitea)에 저장될 저장소 이릅니다.
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
version: bwc/v2 # bwc 버전 정보입니다.
|
||||||
|
spec:
|
||||||
|
appName: sampyo-dio-app # 앱의 이름입니다.
|
||||||
|
runFile: main.py # 앱의 실행 파일입니다.
|
||||||
|
env:
|
||||||
|
bin: python3 # 앱을 실행할 바이너라 파일 종류입니다.(장비에 따라 다르므로 확인 후 정의해야 합니다.)
|
||||||
|
virtualEnv: base # 사용할 가상환경 이름입니다.
|
||||||
|
package: requirements.txt # 설치할 Python 패키지 정보 파일입니다.(기본 값은 requirement.txt 입니다.)
|
||||||
|
stackbase:
|
||||||
|
tagName: v0.0.13 # Stackbase(gitea)에 릴리즈 태그명 입니다.
|
||||||
|
repoName: sampyo-dio # Stackbase(gitea)에 저장될 저장소 이릅니다.
|
611
main.py
611
main.py
|
@ -1,18 +1,611 @@
|
||||||
import sdtcloudpubsub
|
import json
|
||||||
import time
|
import time
|
||||||
|
import sys, signal
|
||||||
|
import gpiod
|
||||||
|
from pymodbus.client import ModbusTcpClient
|
||||||
|
# import AWSIoTPythonSDK.MQTTLib as AWSIoTPyMQTT
|
||||||
|
import sdtcloudnodeqmqtt
|
||||||
|
import pytz
|
||||||
|
from datetime import datetime
|
||||||
|
import threading, socket
|
||||||
import uuid
|
import uuid
|
||||||
|
import logging
|
||||||
|
from logging.handlers import RotatingFileHandler
|
||||||
|
|
||||||
sdtcloud = sdtcloudpubsub.sdtcloudpubsub()
|
def Motor(chip, status, action):
|
||||||
mqttClient = sdtcloud.setClient(f"device-app-{uuid.uuid1()}") # parameter is client ID(string)
|
if action == 'On':
|
||||||
|
status[0] = 1
|
||||||
|
else: # action == 'Off'
|
||||||
|
status[0] = 0
|
||||||
|
|
||||||
|
chip.set_values(status)
|
||||||
|
|
||||||
|
def Valve_Vent(chip, status, action):
|
||||||
|
if action == 'On':
|
||||||
|
status[1] = 1
|
||||||
|
else: # action == 'Off'
|
||||||
|
status[1] = 0
|
||||||
|
|
||||||
|
chip.set_values(status)
|
||||||
|
|
||||||
|
def Valve_MixedWater(chip, status, action):
|
||||||
|
if action == 'On':
|
||||||
|
status[2] = 1
|
||||||
|
else: # action == 'Off'
|
||||||
|
status[2] = 0
|
||||||
|
|
||||||
|
chip.set_values(status)
|
||||||
|
|
||||||
|
def Valve_PureWater(chip, status, action, duration=7):
|
||||||
|
global pure_valve_status
|
||||||
|
|
||||||
|
status[2] = 0
|
||||||
|
status[3] = 0
|
||||||
|
chip.set_values(status)
|
||||||
|
time.sleep(0.05)
|
||||||
|
|
||||||
|
if pure_valve_status != 0 and action == 'Off':
|
||||||
|
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[3] = 0
|
||||||
|
chip.set_values(status)
|
||||||
|
time.sleep(duration)
|
||||||
|
if duration >= 7:
|
||||||
|
pure_valve_status = 2
|
||||||
|
elif duration < 7:
|
||||||
|
pure_valve_status = 1
|
||||||
|
|
||||||
|
status[2] = 0
|
||||||
|
status[3] = 0
|
||||||
|
chip.set_values(status)
|
||||||
|
time.sleep(0.05)
|
||||||
|
|
||||||
|
# def Valve_EnterWater(chip, status, action):
|
||||||
|
def Valve_EnterWater(chip, status, action, duration=7):
|
||||||
|
# if action == 'On':
|
||||||
|
# status[4] = 1
|
||||||
|
# else: # action == 'Off'
|
||||||
|
# status[4] = 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':
|
||||||
|
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':
|
||||||
|
status[4] = 1
|
||||||
|
else: # action == 'Off'
|
||||||
|
status[4] = 0
|
||||||
|
|
||||||
|
chip.set_values(status)
|
||||||
|
|
||||||
|
def Measure_Weight(client):
|
||||||
|
# print('in')
|
||||||
|
val = 0
|
||||||
|
try:
|
||||||
|
result = client.read_holding_registers(1, 1)
|
||||||
|
if not result:
|
||||||
|
print(f'Error: {result}')
|
||||||
|
else:
|
||||||
|
val = result.registers[0]
|
||||||
|
val -= 1000
|
||||||
|
val /= 1000
|
||||||
|
# print(f'value: {val}')
|
||||||
|
except Exception as e:
|
||||||
|
print(f'Measure_Weight Error: {e}')
|
||||||
|
pass
|
||||||
|
|
||||||
|
return float(val)
|
||||||
|
|
||||||
|
def Calculate_Concentration(weight):
|
||||||
|
global data, volume_water
|
||||||
|
data['data']['weight'] = weight
|
||||||
|
result = (float(weight) * volume_water * 128.5) - 126.11 # 1000 / 531 = 1.883239171
|
||||||
|
data['data']['concentration'] = result
|
||||||
|
# print(f'{weight}, {result}')
|
||||||
|
return result
|
||||||
|
|
||||||
|
def Set_Zero(client):
|
||||||
|
client.write_coil(1, 1)
|
||||||
|
|
||||||
|
def Command_Read():
|
||||||
|
global client, main_valve_status, logger
|
||||||
|
|
||||||
|
with open('./control.json', 'r') as f:
|
||||||
|
cmd = json.load(f)
|
||||||
|
|
||||||
|
if cmd['type'] == 'auto':
|
||||||
|
main_duration = float(cmd['device']['main']['duration'])
|
||||||
|
pure_duration = float(cmd['device']['pure']['duration'])
|
||||||
|
step0_duration = float(cmd['working-time']['step0'])
|
||||||
|
step1_duration = float(cmd['working-time']['step1'])
|
||||||
|
step2_duration = float(cmd['working-time']['step2'])
|
||||||
|
step3_duration = float(cmd['working-time']['step3'])
|
||||||
|
step4_duration = float(cmd['working-time']['step4'])
|
||||||
|
step5_duration = float(cmd['working-time']['step5'])
|
||||||
|
step6_duration = float(cmd['working-time']['step6'])
|
||||||
|
step7_duration = float(cmd['working-time']['step7'])
|
||||||
|
step8_duration = float(cmd['working-time']['step8'])
|
||||||
|
step9_duration = float(cmd['working-time']['step9'])
|
||||||
|
|
||||||
|
|
||||||
|
# Step 0. Mesure init weight before starting the sequence
|
||||||
|
time.sleep(step0_duration)
|
||||||
|
start = Measure_Weight(client=client)
|
||||||
|
|
||||||
|
# Step 1. Vent pured water before input mixed water
|
||||||
|
# Target valve status: [Motor: Off, Vent: On, Pure: Off, Enter: On, Main: On]
|
||||||
|
# Valve_EnterWater(chip=output_lines, status=status, action='On')
|
||||||
|
Valve_MainWater(chip=output_lines, status=status, action='On')
|
||||||
|
time.sleep(0.5)
|
||||||
|
Valve_Vent(chip=output_lines, status=status, action='On')
|
||||||
|
time.sleep(0.5)
|
||||||
|
# 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(step1_duration)
|
||||||
|
|
||||||
|
# Step 2. Empty the remaining pure water
|
||||||
|
# Target valve status: [Motor: Off, Vent: On, Pure: Off, Enter: Off, Main: On]
|
||||||
|
Valve_EnterWater(chip=output_lines, status=status, action='Off')
|
||||||
|
time.sleep(step2_duration)
|
||||||
|
|
||||||
|
# Step 3. Input the mixed water
|
||||||
|
# Target valve status: [Motor: Off, Vent: Off, Pure: Off, Enter: On, Main: On]
|
||||||
|
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', duration=main_duration)
|
||||||
|
time.sleep(step3_duration)
|
||||||
|
|
||||||
|
# Step 4. Mesure the weight
|
||||||
|
# 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')
|
||||||
|
time.sleep(step4_duration)
|
||||||
|
|
||||||
|
|
||||||
|
end = Measure_Weight(client=client)
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
res = 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.
|
||||||
|
# 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')
|
||||||
|
time.sleep(0.5)
|
||||||
|
# Valve_PureWater(chip=output_lines, status=status, action='On', duration=pure_duration)
|
||||||
|
Valve_PureWater(chip=output_lines, status=status, action='On')
|
||||||
|
time.sleep(step5_duration)
|
||||||
|
|
||||||
|
# Step 6. Drain mixed water
|
||||||
|
# Target valve status: [Motor: Off, Vent: On, Pure: On, Enter: Off, Main: Off]
|
||||||
|
Valve_EnterWater(chip=output_lines, status=status, action='Off')
|
||||||
|
time.sleep(step6_duration)
|
||||||
|
|
||||||
|
# Step 7. Input pure water and clean
|
||||||
|
# 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')
|
||||||
|
time.sleep(0.5)
|
||||||
|
Motor(chip=output_lines, status=status, action='On')
|
||||||
|
time.sleep(step7_duration)
|
||||||
|
|
||||||
|
# Step 8. Drain pure Water
|
||||||
|
# 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')
|
||||||
|
time.sleep(0.5)
|
||||||
|
Valve_PureWater(chip=output_lines, status=status, action='Off')
|
||||||
|
time.sleep(step8_duration)
|
||||||
|
|
||||||
|
# Step 9. Stop moter
|
||||||
|
# Target valve status: [Motor: Off, Vent: On, Pure: Off, Enter: Off, Main: Off]
|
||||||
|
Motor(chip=output_lines, status=status, action='Off')
|
||||||
|
time.sleep(step9_duration)
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|
||||||
|
elif cmd['type'] == 'clean':
|
||||||
|
logger.debug(f"[clean] duration: {int(cmd['maintenance']['clean']['duration'])}")
|
||||||
|
clean_system()
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
else: # cmd['type'] == 'manual'
|
||||||
|
Motor(chip=output_lines, status=status, action=cmd['device']['motor']['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_PureWater(chip=output_lines, status=status, action=cmd['device']['pure']['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:
|
||||||
|
Valve_PureWater(chip=output_lines, status=status, action=cmd['device']['pure']['action'])
|
||||||
|
else:
|
||||||
|
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:
|
||||||
|
Valve_EnterWater(chip=output_lines, status=status, action=cmd['device']['enter']['action'])
|
||||||
|
else:
|
||||||
|
Valve_EnterWater(chip=output_lines, status=status, action=cmd['device']['enter']['action'], duration=cmd['device']['main']['duration'])
|
||||||
|
|
||||||
|
|
||||||
|
if cmd['device']['measure']['action'] == 'On':
|
||||||
|
result = Measure_Weight(client=client)
|
||||||
|
Calculate_Concentration(result)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if cmd['device']['setzero']['action'] == 'On':
|
||||||
|
Set_Zero(client=client)
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def clean_system():
|
||||||
|
global main_valve_status
|
||||||
|
with open('./control.json', 'r') as f:
|
||||||
|
cmd = json.load(f)
|
||||||
|
|
||||||
|
clean_duration = int(cmd['maintenance']['clean']['duration'])
|
||||||
|
|
||||||
|
if cmd['type'] == 'clean':
|
||||||
|
Valve_EnterWater(chip=output_lines, status=status, action='Off')
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
Valve_MainWater(chip=output_lines, status=status, action='On')
|
||||||
|
time.sleep(0.5)
|
||||||
|
Valve_PureWater(chip=output_lines, status=status, action='On')
|
||||||
|
time.sleep(clean_duration)
|
||||||
|
|
||||||
|
Valve_MainWater(chip=output_lines, status=status, action='Off')
|
||||||
|
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')
|
||||||
|
time.sleep(0.5)
|
||||||
|
Valve_Vent(chip=output_lines, status=status, action='Off')
|
||||||
|
time.sleep(0.5)
|
||||||
|
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.
|
||||||
|
|
||||||
|
# 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:
|
while True:
|
||||||
msg = {
|
start = time.time()
|
||||||
"message": "Hello World"
|
result = Command_Read()
|
||||||
}
|
|
||||||
sdtcloud.pubMessage(mqttClient, msg)
|
if result:
|
||||||
time.sleep(2)
|
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__":
|
if __name__ == "__main__":
|
||||||
runAction()
|
# 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,0 +1,383 @@
|
||||||
|
import ssl
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
import argparse
|
||||||
|
import sys, signal
|
||||||
|
import gpiod
|
||||||
|
from pymodbus.client import ModbusTcpClient
|
||||||
|
#import AWSIoTPythonSDK.MQTTLib as AWSIoTPyMQTT
|
||||||
|
import sdtcloudnodeqmqtt
|
||||||
|
import asyncio, pytz
|
||||||
|
from datetime import datetime
|
||||||
|
import threading, socket
|
||||||
|
|
||||||
|
def Motor(chip, status, action):
|
||||||
|
if action == 'On':
|
||||||
|
status[0] = 1
|
||||||
|
else: # action == 'Off'
|
||||||
|
status[0] = 0
|
||||||
|
|
||||||
|
chip.set_values(status)
|
||||||
|
|
||||||
|
def Valve_Vent(chip, status, action):
|
||||||
|
if action == 'On':
|
||||||
|
status[1] = 1
|
||||||
|
else: # action == 'Off'
|
||||||
|
status[1] = 0
|
||||||
|
|
||||||
|
chip.set_values(status)
|
||||||
|
|
||||||
|
def Valve_MixedWater(chip, status, action):
|
||||||
|
if action == 'On':
|
||||||
|
status[2] = 1
|
||||||
|
else: # action == 'Off'
|
||||||
|
status[2] = 0
|
||||||
|
|
||||||
|
chip.set_values(status)
|
||||||
|
|
||||||
|
def Valve_PureWater(chip, status, action):
|
||||||
|
if action == 'On':
|
||||||
|
status[3] = 1
|
||||||
|
else: # action == 'Off'
|
||||||
|
status[3] = 0
|
||||||
|
|
||||||
|
chip.set_values(status)
|
||||||
|
|
||||||
|
def Measure_Weight(client):
|
||||||
|
# print('In')
|
||||||
|
try:
|
||||||
|
result = client.read_holding_registers(1, 1)
|
||||||
|
if result.isError():
|
||||||
|
print(f'Error: {result}')
|
||||||
|
else:
|
||||||
|
val = result.registers[0]
|
||||||
|
val -= 1000
|
||||||
|
val /= 1000
|
||||||
|
|
||||||
|
# print(f'value: {val}')
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return val
|
||||||
|
|
||||||
|
def Calculate_Concentration(weight):
|
||||||
|
global data
|
||||||
|
data['data']['weight'] = weight
|
||||||
|
result = (float(weight) * 1.883239171 * 128.5) - 126.11 # 1000 / 531 = 1.883239171
|
||||||
|
data['data']['concentration'] = result
|
||||||
|
# print(f'{weight}, {result}')
|
||||||
|
|
||||||
|
# def Set_Zero(client):
|
||||||
|
# client.write_coil(1, 1)
|
||||||
|
|
||||||
|
def Command_Read():
|
||||||
|
with open('./control.json', 'r') as f:
|
||||||
|
cmd = json.load(f)
|
||||||
|
|
||||||
|
if cmd['type'] == 'auto':
|
||||||
|
|
||||||
|
Valve_Vent(chip=output_lines, status=status, action='Off')
|
||||||
|
Motor(chip=output_lines, status=status, action='Off')
|
||||||
|
|
||||||
|
mixed_duration = int(cmd['device']['mixed']['duration'])
|
||||||
|
pure_duration = int(cmd['device']['pure']['duration'])
|
||||||
|
vent_duration = int(cmd['device']['vent']['duration'])
|
||||||
|
|
||||||
|
time.sleep(5)
|
||||||
|
start = Measure_Weight(client=client)
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
|
# input mixed water
|
||||||
|
Valve_MixedWater(chip=output_lines, status=status, action='On')
|
||||||
|
time.sleep(mixed_duration)
|
||||||
|
Valve_MixedWater(chip=output_lines, status=status, action='Off')
|
||||||
|
time.sleep(10)
|
||||||
|
|
||||||
|
# measure weight
|
||||||
|
end = Measure_Weight(client=client)
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
Calculate_Concentration(weight=(float(end)-float(start)))
|
||||||
|
|
||||||
|
# vent mixed water
|
||||||
|
Valve_Vent(chip=output_lines, status=status, action='On')
|
||||||
|
time.sleep(0.5)
|
||||||
|
Motor(chip=output_lines, status=status, action='On')
|
||||||
|
time.sleep(vent_duration)
|
||||||
|
Motor(chip=output_lines, status=status, action='Off')
|
||||||
|
time.sleep(0.5)
|
||||||
|
Valve_Vent(chip=output_lines, status=status, action='Off')
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
# input pure water
|
||||||
|
Valve_PureWater(chip=output_lines, status=status, action='On')
|
||||||
|
time.sleep(pure_duration)
|
||||||
|
Valve_PureWater(chip=output_lines, status=status, action='Off')
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
# vent pure water
|
||||||
|
Valve_Vent(chip=output_lines, status=status, action='On')
|
||||||
|
time.sleep(0.5)
|
||||||
|
Motor(chip=output_lines, status=status, action='On')
|
||||||
|
time.sleep(vent_duration)
|
||||||
|
Motor(chip=output_lines, status=status, action='Off')
|
||||||
|
time.sleep(0.5)
|
||||||
|
Valve_Vent(chip=output_lines, status=status, action='Off')
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
else: # cmd['type'] == 'manual'
|
||||||
|
Motor(chip=output_lines, status=status, action=cmd['device']['motor']['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_PureWater(chip=output_lines, status=status, action=cmd['device']['pure']['action'])
|
||||||
|
if cmd['device']['measure']['action'] == 'On':
|
||||||
|
result = Measure_Weight(client=client)
|
||||||
|
Calculate_Concentration(result)
|
||||||
|
if cmd['device']['setzero']['action'] == 'On':
|
||||||
|
Set_Zero(client=client)
|
||||||
|
|
||||||
|
def connectMQTT(clientID, projectCode):
|
||||||
|
CLIENT_ID = clientID
|
||||||
|
ENDPOINT = "avk03ee629rck-ats.iot.ap-northeast-2.amazonaws.com"
|
||||||
|
PATH_TO_CERTIFICATE = f"/etc/sdt/cert/{projectCode}-certificate.pem"
|
||||||
|
PATH_TO_PRIVATE_KEY = f"/etc/sdt/cert/{projectCode}-private.pem"
|
||||||
|
PATH_TO_AMAZON_ROOT_CA_1 = f"/etc/sdt/cert/AmazonRootCA1.pem"
|
||||||
|
|
||||||
|
myAWSIoTMQTTClient = AWSIoTPyMQTT.AWSIoTMQTTClient(CLIENT_ID)
|
||||||
|
myAWSIoTMQTTClient.configureEndpoint(ENDPOINT, 8883)
|
||||||
|
myAWSIoTMQTTClient.configureCredentials(PATH_TO_AMAZON_ROOT_CA_1, PATH_TO_PRIVATE_KEY, PATH_TO_CERTIFICATE)
|
||||||
|
|
||||||
|
myAWSIoTMQTTClient.configureMQTTOperationTimeout(5)
|
||||||
|
myAWSIoTMQTTClient.configureConnectDisconnectTimeout(10)
|
||||||
|
myAWSIoTMQTTClient.configureOfflinePublishQueueing(-1) # Infinite offline Publish queueing
|
||||||
|
myAWSIoTMQTTClient.configureDrainingFrequency(2) # Draining: 2 Hz
|
||||||
|
|
||||||
|
return myAWSIoTMQTTClient
|
||||||
|
|
||||||
|
def publishMsg(mqttClient, topic, msg):
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
mqttClient.connect()
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
print(f'Connection Fail: {e}')
|
||||||
|
continue
|
||||||
|
|
||||||
|
msg['timestamp'] = int(time.time() * 1000)
|
||||||
|
|
||||||
|
# Publish message to server desired number of times.
|
||||||
|
# print('Begin Publish')
|
||||||
|
mqttClient.publish(topic=topic, payload=json.dumps(msg), QoS=1)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
mqttClient.disconnect()
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
print(f'Disconnection Fail: {e}')
|
||||||
|
continue
|
||||||
|
|
||||||
|
def runAction(projectCode, assetCode, con_info):
|
||||||
|
# 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
|
||||||
|
mqttClient1 = connectMQTT("device-app-test1", projectCode)
|
||||||
|
mqttClient2 = connectMQTT("device-app-test2", projectCode)
|
||||||
|
mqttClient3 = connectMQTT("device-app-test3", projectCode)
|
||||||
|
mqttClient4 = connectMQTT("device-app-test4", projectCode)
|
||||||
|
mqttClient5 = connectMQTT("device-app-test5", projectCode)
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
topic = f"sdtcloud/{projectCode}/{assetCode}/app/{con_info['appId']}/data"
|
||||||
|
|
||||||
|
cnt = 0
|
||||||
|
while True:
|
||||||
|
start = time.time()
|
||||||
|
Command_Read()
|
||||||
|
publishMsg(mqttlist[cnt], topic, data)
|
||||||
|
end = time.time()
|
||||||
|
|
||||||
|
cnt += 1
|
||||||
|
|
||||||
|
if cnt == 5:
|
||||||
|
cnt = 0
|
||||||
|
|
||||||
|
diff = end - start
|
||||||
|
if diff < 3:
|
||||||
|
time.sleep(3 - diff)
|
||||||
|
|
||||||
|
def handle_client(conn, ip, port):
|
||||||
|
global data
|
||||||
|
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)
|
||||||
|
|
||||||
|
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
|
||||||
|
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] == '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 # "25.7.57.1"
|
||||||
|
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 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')
|
||||||
|
|
||||||
|
client.close()
|
||||||
|
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
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]
|
||||||
|
|
||||||
|
signal.signal(signal.SIGINT, exit_handler)
|
||||||
|
|
||||||
|
with open('./config.json', encoding='UTF-8') as f:
|
||||||
|
jsonData = json.load(f)
|
||||||
|
|
||||||
|
modbus_addr = jsonData['modbus-server']['address']
|
||||||
|
modbus_port = jsonData['modbus-server']['port']
|
||||||
|
|
||||||
|
client = ModbusTcpClient(modbus_addr, modbus_port)
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('-app',help='')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# ROOT_PATH = f'/usr/local/sdt/app/{args.app}'
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"timestamp": 0,
|
||||||
|
"data":{
|
||||||
|
"weight": 0,
|
||||||
|
"concentration": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
## Get ProjectCode and AssetCode
|
||||||
|
with open(f'/etc/sdt/device.config/config.json', encoding='UTF-8') as f:
|
||||||
|
codeData = json.load(f)
|
||||||
|
|
||||||
|
## Execution main funcion
|
||||||
|
operation_thread = threading.Thread(target=runAction, args=(codeData["projectcode"], codeData["assetcode"], jsonData))
|
||||||
|
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,0 +1,18 @@
|
||||||
|
import sdtcloudpubsub
|
||||||
|
import time
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
sdtcloud = sdtcloudpubsub.sdtcloudpubsub()
|
||||||
|
mqttClient = sdtcloud.setClient(f"device-app-{uuid.uuid1()}") # parameter is client ID(string)
|
||||||
|
|
||||||
|
def runAction():
|
||||||
|
while True:
|
||||||
|
msg = {
|
||||||
|
"message": "Hello World"
|
||||||
|
}
|
||||||
|
sdtcloud.pubMessage(mqttClient, msg)
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
runAction()
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
# Write package's name that need your app.
|
||||||
|
#awsiotsdk
|
||||||
|
pyyaml
|
||||||
|
gpiod
|
||||||
|
pymodbus
|
||||||
|
pytz
|
||||||
|
#sdtcloudpubsub
|
|
@ -0,0 +1,375 @@
|
||||||
|
import ssl
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
import argparse
|
||||||
|
import sys, signal
|
||||||
|
import gpiod
|
||||||
|
from pymodbus.client import ModbusTcpClient
|
||||||
|
import AWSIoTPythonSDK.MQTTLib as AWSIoTPyMQTT
|
||||||
|
import asyncio, pytz
|
||||||
|
from datetime import datetime
|
||||||
|
import threading, socket
|
||||||
|
|
||||||
|
def Motor(chip, status, action):
|
||||||
|
if action == 'On':
|
||||||
|
status[0] = 1
|
||||||
|
else: # action == 'Off'
|
||||||
|
status[0] = 0
|
||||||
|
|
||||||
|
chip.set_values(status)
|
||||||
|
|
||||||
|
def Valve_Vent(chip, status, action):
|
||||||
|
if action == 'On':
|
||||||
|
status[1] = 1
|
||||||
|
else: # action == 'Off'
|
||||||
|
status[1] = 0
|
||||||
|
|
||||||
|
chip.set_values(status)
|
||||||
|
|
||||||
|
def Valve_MixedWater(chip, status, action):
|
||||||
|
if action == 'On':
|
||||||
|
status[2] = 1
|
||||||
|
else: # action == 'Off'
|
||||||
|
status[2] = 0
|
||||||
|
|
||||||
|
chip.set_values(status)
|
||||||
|
|
||||||
|
def Valve_PureWater(chip, status, action):
|
||||||
|
if action == 'On':
|
||||||
|
status[3] = 1
|
||||||
|
else: # action == 'Off'
|
||||||
|
status[3] = 0
|
||||||
|
|
||||||
|
chip.set_values(status)
|
||||||
|
|
||||||
|
def Measure_Weight(client):
|
||||||
|
# print('In')
|
||||||
|
try:
|
||||||
|
result = client.read_holding_registers(1, 1)
|
||||||
|
if result.isError():
|
||||||
|
print(f'Error: {result}')
|
||||||
|
else:
|
||||||
|
val = result.registers[0]
|
||||||
|
val -= 1000
|
||||||
|
val /= 1000
|
||||||
|
|
||||||
|
# print(f'value: {val}')
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return val
|
||||||
|
|
||||||
|
def Calculate_Concentration(weight):
|
||||||
|
global data
|
||||||
|
data['data']['weight'] = weight
|
||||||
|
result = (float(weight) * 1.883239171 * 128.5) - 126.11 # 1000 / 531 = 1.883239171
|
||||||
|
data['data']['concentration'] = result
|
||||||
|
# print(f'{weight}, {result}')
|
||||||
|
|
||||||
|
def Set_Zero(client):
|
||||||
|
client.write_coil(1, 1)
|
||||||
|
|
||||||
|
def Command_Read():
|
||||||
|
with open('./control.json', 'r') as f:
|
||||||
|
cmd = json.load(f)
|
||||||
|
|
||||||
|
if cmd['type'] == 'auto':
|
||||||
|
|
||||||
|
Valve_Vent(chip=output_lines, status=status, action='Off')
|
||||||
|
Motor(chip=output_lines, status=status, action='Off')
|
||||||
|
|
||||||
|
# set zero
|
||||||
|
# Set_Zero(client=client)
|
||||||
|
time.sleep(5)
|
||||||
|
start = Measure_Weight(client=client)
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
|
# input mixed water
|
||||||
|
Valve_MixedWater(chip=output_lines, status=status, action='On')
|
||||||
|
time.sleep(19)
|
||||||
|
Valve_MixedWater(chip=output_lines, status=status, action='Off')
|
||||||
|
# time.sleep(20)
|
||||||
|
time.sleep(10)
|
||||||
|
|
||||||
|
# measure weight
|
||||||
|
end = Measure_Weight(client=client)
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
Calculate_Concentration(weight=(float(end)-float(start)))
|
||||||
|
|
||||||
|
# vent mixed water
|
||||||
|
Valve_Vent(chip=output_lines, status=status, action='On')
|
||||||
|
time.sleep(0.5)
|
||||||
|
Motor(chip=output_lines, status=status, action='On')
|
||||||
|
time.sleep(40)
|
||||||
|
Motor(chip=output_lines, status=status, action='Off')
|
||||||
|
time.sleep(0.5)
|
||||||
|
Valve_Vent(chip=output_lines, status=status, action='Off')
|
||||||
|
|
||||||
|
# input pure water
|
||||||
|
Valve_PureWater(chip=output_lines, status=status, action='On')
|
||||||
|
time.sleep(19)
|
||||||
|
Valve_PureWater(chip=output_lines, status=status, action='Off')
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
# vent pure water
|
||||||
|
Valve_Vent(chip=output_lines, status=status, action='On')
|
||||||
|
time.sleep(0.5)
|
||||||
|
Motor(chip=output_lines, status=status, action='On')
|
||||||
|
time.sleep(40)
|
||||||
|
Motor(chip=output_lines, status=status, action='Off')
|
||||||
|
time.sleep(0.5)
|
||||||
|
Valve_Vent(chip=output_lines, status=status, action='Off')
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
|
else: # cmd['type'] == 'manual'
|
||||||
|
Motor(chip=output_lines, status=status, action=cmd['device']['motor']['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_PureWater(chip=output_lines, status=status, action=cmd['device']['pure']['action'])
|
||||||
|
if cmd['device']['measure']['action'] == 'On':
|
||||||
|
result = Measure_Weight(client=client)
|
||||||
|
Calculate_Concentration(result)
|
||||||
|
if cmd['device']['setzero']['action'] == 'On':
|
||||||
|
Set_Zero(client=client)
|
||||||
|
|
||||||
|
def connectMQTT(clientID, projectCode):
|
||||||
|
CLIENT_ID = clientID
|
||||||
|
ENDPOINT = "avk03ee629rck-ats.iot.ap-northeast-2.amazonaws.com"
|
||||||
|
PATH_TO_CERTIFICATE = f"/etc/sdt/cert/{projectCode}-certificate.pem"
|
||||||
|
PATH_TO_PRIVATE_KEY = f"/etc/sdt/cert/{projectCode}-private.pem"
|
||||||
|
PATH_TO_AMAZON_ROOT_CA_1 = f"/etc/sdt/cert/AmazonRootCA1.pem"
|
||||||
|
|
||||||
|
myAWSIoTMQTTClient = AWSIoTPyMQTT.AWSIoTMQTTClient(CLIENT_ID)
|
||||||
|
myAWSIoTMQTTClient.configureEndpoint(ENDPOINT, 8883)
|
||||||
|
myAWSIoTMQTTClient.configureCredentials(PATH_TO_AMAZON_ROOT_CA_1, PATH_TO_PRIVATE_KEY, PATH_TO_CERTIFICATE)
|
||||||
|
|
||||||
|
myAWSIoTMQTTClient.configureMQTTOperationTimeout(5)
|
||||||
|
myAWSIoTMQTTClient.configureConnectDisconnectTimeout(10)
|
||||||
|
myAWSIoTMQTTClient.configureOfflinePublishQueueing(-1) # Infinite offline Publish queueing
|
||||||
|
myAWSIoTMQTTClient.configureDrainingFrequency(2) # Draining: 2 Hz
|
||||||
|
|
||||||
|
return myAWSIoTMQTTClient
|
||||||
|
|
||||||
|
def publishMsg(mqttClient, topic, msg):
|
||||||
|
# Make the copip3 nnect() call
|
||||||
|
# mqttClient.connect()
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
mqttClient.connect()
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
print(f'Connection Fail: {e}')
|
||||||
|
continue
|
||||||
|
|
||||||
|
msg['timestamp'] = int(time.time() * 1000)
|
||||||
|
|
||||||
|
# Publish message to server desired number of times.
|
||||||
|
# print('Begin Publish')
|
||||||
|
mqttClient.publish(topic=topic, payload=json.dumps(msg), QoS=1)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
mqttClient.disconnect()
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
print(f'Disconnection Fail: {e}')
|
||||||
|
continue
|
||||||
|
|
||||||
|
def runAction(projectCode, assetCode):
|
||||||
|
# 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
|
||||||
|
mqttClient1 = connectMQTT("device-app-test1", projectCode)
|
||||||
|
mqttClient2 = connectMQTT("device-app-test2", projectCode)
|
||||||
|
mqttClient3 = connectMQTT("device-app-test3", projectCode)
|
||||||
|
mqttClient4 = connectMQTT("device-app-test4", projectCode)
|
||||||
|
mqttClient5 = connectMQTT("device-app-test5", projectCode)
|
||||||
|
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.
|
||||||
|
with open('./config.json', encoding='UTF-8') as f:
|
||||||
|
jsonData = json.load(f)
|
||||||
|
|
||||||
|
topic = f"sdtcloud/{projectCode}/{assetCode}/app/{jsonData['appId']}/data"
|
||||||
|
|
||||||
|
cnt = 0
|
||||||
|
while True:
|
||||||
|
start = time.time()
|
||||||
|
Command_Read()
|
||||||
|
# publishMsg(mqttlist[cnt], topic, data)
|
||||||
|
end = time.time()
|
||||||
|
|
||||||
|
cnt += 1
|
||||||
|
|
||||||
|
if cnt == 5:
|
||||||
|
cnt = 0
|
||||||
|
|
||||||
|
diff = end - start
|
||||||
|
if diff < 3:
|
||||||
|
time.sleep(3 - diff)
|
||||||
|
|
||||||
|
def handle_client(conn, ip, port):
|
||||||
|
global data
|
||||||
|
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)
|
||||||
|
|
||||||
|
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
|
||||||
|
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] == '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():
|
||||||
|
host = "25.7.57.1"
|
||||||
|
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 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')
|
||||||
|
|
||||||
|
client.close()
|
||||||
|
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
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]
|
||||||
|
|
||||||
|
signal.signal(signal.SIGINT, exit_handler)
|
||||||
|
|
||||||
|
client = ModbusTcpClient('25.7.55.237', 5020)
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('-app',help='')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# ROOT_PATH = f'/usr/local/sdt/app/{args.app}'
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"timestamp": 0,
|
||||||
|
"data":{
|
||||||
|
"weight": 0,
|
||||||
|
"concentration": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
## Get ProjectCode and AssetCode
|
||||||
|
with open(f'/etc/sdt/device.config/config.json', encoding='UTF-8') as f:
|
||||||
|
codeData = json.load(f)
|
||||||
|
|
||||||
|
## Execution main funcion
|
||||||
|
operation_thread = threading.Thread(target=runAction, args=(codeData["projectcode"], codeData["assetcode"]))
|
||||||
|
operation_thread.start()
|
||||||
|
|
||||||
|
## Execution TCP/IP server
|
||||||
|
start_server()
|
Loading…
Reference in New Issue