115 lines
3.6 KiB
Python
115 lines
3.6 KiB
Python
|
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())
|