diff --git a/README.md b/README.md index 4f16b9d..20e6c43 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,30 @@ -# aquarack-sensor-collector +# 이 코드 템플릿은 SDT Cloud 환경에서 mqtt 메세지를 발행하는 코드입니다. -Your repository description \ No newline at end of file +# 패키지 설치 +- 코드는 sdtcloudpubsub 패키지를 사용합니다. 아래 명령어로 패키지를 다운로드 해야합니다. +```bash +$ pip install sdtcloudpubsub +``` + +# 코드 작성 +- 코드는 runAction 함수에서 동작하고자 하는 기능을 작성합니다. +- msg 변수는 발행될 메세지 입니다. +- sdtcloudpubsub의 pubMessage 함수는 발행할 메세지 내용인 dictionary 타입 변수를 입력 받아 처리합니다. + +# 메세지 발행 +- 다음 변수로 메세지를 발행하는 코드를 작성하면... +```bash +msg = { + "message": "Hello World" +} +``` +- 실제로 발행되는 메세지은 다음과 같습니다. +```bash +msg = { + "data": { + "message": "Hello World" + }, + "timestamp": 12312311... +} + +``` diff --git a/config.json b/config.json new file mode 100644 index 0000000..07d9365 --- /dev/null +++ b/config.json @@ -0,0 +1,10 @@ +{ + "get_data_interval": 1, + "set_zero_temperature": "n", + "ref_zero_point": { + "oilInFlowRate": 3989, + "oilOutFlowRate": 3978, + "waterInFlowRate": 3984, + "waterOutFlowRate": 4000 + } +} diff --git a/framework.yaml b/framework.yaml new file mode 100644 index 0000000..aa0df65 --- /dev/null +++ b/framework.yaml @@ -0,0 +1,12 @@ +version: bwc/v2 # bwc 버전 정보입니다. +spec: + appName: aquarack-sensor-collector-app # 앱의 이름입니다. + runFile: main.py # 앱의 실행 파일입니다. + env: + bin: python3 + virtualEnv: aquarack # 사용할 가상환경 이름입니다. + package: requirements.txt # 설치할 Python 패키지 정보 파일입니다.(기본 값은 requirement.txt 입니다.) + runtime: python3.9 +stackbase: + tagName: v1.0.1 # Stackbase(gitea)에 릴리즈 태그명 입니다. + repoName: aquarack-sensor-collector # Satackbase(gitea)에 저장될 저장소 이릅니다. diff --git a/main.py b/main.py new file mode 100644 index 0000000..df43a3e --- /dev/null +++ b/main.py @@ -0,0 +1,138 @@ +import sdtcloudpubsub +import time +import uuid +from pymodbus.client import ModbusSerialClient as ModbusClient +import os, json +from collections import Counter + +sdtcloud = sdtcloudpubsub.sdtcloudpubsub() +sdtcloud.setClient(f"device-app-{uuid.uuid1()}") # parameter is client ID(string) + +def get_point_temperature(serial_obj): + global t_col + # CWT-TM-320s + res_dict = { + "topLeftTemperature": 999.99, + "topRightTemperature": 999.99, + "bottomLeftTemperature": 999.99, + "bottomRightTemperature": 999.99 + } + points = [1, 3, 7, 9] + + try: + res = serial_obj.read_holding_registers(address=32, count=32, slave=2) + # print(res) + for i, j in zip(t_col, points): + res_dict[i] = res.registers[j - 1] * 0.1 + except Exception as e: + pass + return res_dict + +def get_keyence_devices(serial_obj): + global g_zero_point, k_col + # CWT-MB307D + res_dict = { + "oilInFlowRate": 999.99, + "oilInTemperature": 999.99, + "oilOutFlowRate": 999.99, + "oilOutTemperature": 999.99, + + "waterInFlowRate": 999.99, + "waterInTemperature": 999.99, + "waterOutFlowRate": 999.99, + "waterOutTemperature": 999.99 + } + + points = [1, 2, 3, 4, 5, 6, 7, 8] + + try: + res = serial_obj.read_holding_registers(address=50, count=8, slave=5) + + for i, j in enumerate(k_col): + if i % 2 == 0: + res_dict[j] = ((res.registers[i] - g_zero_point[i // 2]) / 16000) * 300 + # print(f'Flow_rate: {flow_rate:.6f}L') + else: + res_dict[j] = ((res.registers[i] - 4000) / 16000) * 100 + # print(f'Temperature: {temperature:.6f} degree') + except Exception as e: + # print(f'Error: {e}') + pass + return res_dict + +def init_zero_detection(serial_obj, config_dict): + global g_zero_point, k_col + + if config_dict['set_zero_temperature'] == 'y': + try: + res = serial_obj.read_holding_registers(address=50, count=8, slave=5) + + for i, j in enumerate(k_col): + if not i % 2: + config_dict['ref_zero_point'][j] = res.registers[i] + + config_dict['set_zero_temperature'] = 'n' + + with open('./config.json', 'w') as f: + json.dump(config_dict, f, indent=4) + except: + return False + + for idx, val in enumerate(k_col): + if not idx % 2: + g_zero_point[idx // 2] = config_dict['ref_zero_point'][val] + + return True + +def runAction(): + sum_data = {} + cnt, cnt_limit = 0, 0 + + while True: + with open('./config.json', 'r') as config: + config_data = json.load(config) + + interval = int(config_data['get_data_interval']) + + if interval <= 5: + cnt_limit = 1 + elif interval <= 1800: + cnt_limit = 10 + else: + cnt_limit = 100 + + init_zero_detection(client1, config_data) + + start = int(time.time() * 1000) + pub_data = { + **get_point_temperature(client1), **get_keyence_devices(client1) + } + print(int(time.time() * 1000), pub_data) + + sum_data = Counter(sum_data) + Counter(pub_data) + end = int(time.time() * 1000) + diff = end - start + sleep_time = int(interval / cnt_limit) - (diff * 0.001) + cnt += 1 + if cnt == cnt_limit: + snd_data = {key: value / cnt_limit for key, value in sum_data.items()} + sdtcloud.pubMessage(snd_data) + cnt = 0 + + time.sleep(sleep_time) + +if __name__ == "__main__": + password = 'Sdt2513!@' + os.system(f'echo "{password}" | sudo chmod 777 /dev/ttyS0') + port_name = '/dev/ttyS0' + client1 = ModbusClient(port=port_name, baudrate=19200, parity='N', stopbits=1, bytesize=8, timeout=0.25) + + client1.connect() + + g_zero_point = [0] * 4 + k_col = ["oilInFlowRate","oilInTemperature","oilOutFlowRate","oilOutTemperature", + "waterInFlowRate","waterInTemperature","waterOutFlowRate","waterOutTemperature"] + t_col = ["topLeftTemperature", "topRightTemperature", "bottomLeftTemperature", "bottomRightTemperature"] + + runAction() + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..da92723 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,8 @@ +# Write package's name that need your app. +awsiotsdk +pyyaml +pymodbus +pyserial +yaml +AWSIoTPythonSDK +#sdtcloudpubsub \ No newline at end of file