diff --git a/README.md b/README.md index 9d0536d..20e6c43 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,30 @@ -# modbusTCP-server-app +# 이 코드 템플릿은 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..76e5298 --- /dev/null +++ b/config.json @@ -0,0 +1,6 @@ +{ + "modbus-server": { + "address": "192.168.0.11", + "port": 5020 + } +} \ No newline at end of file diff --git a/framework.yaml b/framework.yaml new file mode 100644 index 0000000..1f9d2f2 --- /dev/null +++ b/framework.yaml @@ -0,0 +1,11 @@ +version: bwc/v2 # bwc 버전 정보입니다. +spec: + appName: aio-test-app # 앱의 이름입니다. + runFile: main.py # 앱의 실행 파일입니다. + env: + bin: python3 # 앱을 실행할 바이너라 파일 종류입니다.(장비에 따라 다르므로 확인 후 정의해야 합니다.) + virtualEnv: # 사용할 가상환경 이름입니다. + package: requirements.txt # 설치할 Python 패키지 정보 파일입니다.(기본 값은 requirement.txt 입니다.) +stackbase: + tagName: v0.0.3 # Stackbase(gitea)에 릴리즈 태그명 입니다. + repoName: modbusTCP-server-app # Stackbase(gitea)에 저장될 저장소 이릅니다. diff --git a/main.py b/main.py new file mode 100644 index 0000000..704fc8d --- /dev/null +++ b/main.py @@ -0,0 +1,114 @@ +import asyncio +#from pymodbus.server.async_io import ModbusTcpServer +from pymodbus.server.async_io import ModbusTcpServer, StartAsyncTcpServer +from pymodbus.datastore import ModbusSequentialDataBlock +from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext +import comm_m4 +import time +import struct +import signal +import sys + + +async def run_server(): + with open(os.path.join('./config.json'), encoding='UTF-8') as f: + jsonData = json.load + + server = ModbusTcpServer(context, address=(jsonData['modbus-server']['address'], jsonData['modbus-server']['port'])) + + task_input = asyncio.create_task(set_input(store)) + task_output = asyncio.create_task(set_output(store)) + task_stop_output = asyncio.create_task(stop_output(store)) + task_cal = asyncio.create_task(set_cal(store)) + + await asyncio.gather(server.serve_forever(), task_input, task_output, task_stop_output, task_cal) + + +async def set_input(store): + while True: + try: + rsp = store.getValues(16,0, count=10) + if rsp[0] == 1: + data = aio.voltage_once() + byte_data = b''.join(struct.pack('f', d) for d in data) + result = {'registers': [0]*16} + for i in range(8): + result['registers'][2*i+1], result['registers'][2*i] = struct.unpack('H', byte_data[4*i:4*i+2])[0], struct.unpack('H', byte_data[4*i+2:4*i+4])[0] + + send_data = result['registers'] + store.setValues(3,1,send_data) + store.setValues(6,0,[0]) + except Exception as e: + print(f'error input:{e}') + + await asyncio.sleep(1) + + +async def set_output(store): + while True: + try: + rsp = store.getValues(16,20, count=10) + channels = [i + 1 for i, value in enumerate(rsp[:8]) if value != 0] + voltages = [value for value in rsp[:8] if value != 0] + for ch, vol in zip(channels, voltages): + aio.start_output(channel=ch, voltage=vol) + store.setValues(16,20,[0]*10) + except Exception as e: + print(f'error output:{e}') + + await asyncio.sleep(1) + + +async def stop_output(store): + while True: + try: + rsp = store.getValues(16,30, count=10) + channels = [i + 1 for i, value in enumerate(rsp[:8]) if value == 0] + for ch in channels: + aio.stop_output(channel=ch) + store.setValues(16,30,[2]*10) + except Exception as e: + print(f'error stp[]:{e}') + + await asyncio.sleep(1) + + +async def set_cal(store): + while True: + try: + rsp = store.getValues(16,40, count=1) + if rsp[0] == 0: + aio.calibration('AO') + elif rsp[0] == 1: + aio.calibration('AI') + store.setValues(16,40,[2]*6) + except Exception as e: + print(f'error:{e}') + + await asyncio.sleep(1) + + +def exit_handler(signum, frame): + global aio + if aio is not None: + del aio + + sys.exit(0) + + +if __name__ == "__main__": + + aio = comm_m4.AIO() + + signal.signal(signal.SIGINT, exit_handler) + coil_block = ModbusSequentialDataBlock(0, [0] * 100) + holding_block = ModbusSequentialDataBlock(0, [0]*30 + [2]*16 + [0]*(100-36)) + store = ModbusSlaveContext( + co=coil_block, + hr=holding_block + ) + context = ModbusServerContext(slaves=store, single=True) + + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + loop.run_until_complete(run_server()) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..ce4d0c0 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +# Write package's name that need your app. +#awsiotsdk +#pyyaml +#sdtcloudpubsub + +pymodbus