diff --git a/modpypes/client.py b/modpypes/client.py index 14a3625..bcdd94c 100644 --- a/modpypes/client.py +++ b/modpypes/client.py @@ -58,8 +58,9 @@ class ConsoleClient(ConsoleCmd, Client): :param count: number of registers to read, defaults to one This command generates a :class:`ReadCoilsRequest`, - :class:`ReadDiscreteInputsRequest` or :class:`ReadMultipleRegistersRequest` - depending on the address prefix; 1, 5, or 6. + :class:`ReadDiscreteInputsRequest`, :class:`ReadInputRegistersRequest`, + or :class:`ReadMultipleRegistersRequest` depending on the address + prefix; 0, 1, 3, or 4. """ args = args.split() if _debug: ConsoleClient._debug("do_read %r", args) @@ -102,8 +103,11 @@ class ConsoleClient(ConsoleCmd, Client): # coil req = ReadCoilsRequest(register - 1, rcount) elif registerType == 1: - # input discrete + # discrete inputs req = ReadDiscreteInputsRequest(register - 1, 1) + elif registerType == 3: + # input register + req = ReadInputRegistersRequest(register - 1, 1) elif registerType == 4: # holding register req = ReadMultipleRegistersRequest(register - 1, rcount) @@ -122,6 +126,76 @@ class ConsoleClient(ConsoleCmd, Client): # send it along self.request(req) + def do_write(self, args): + """write + + :param addr: IP address of the MODBUS/TCP device or gateway + :param unitID: unit identifier + :param register: register in 5-digit or 6-digit format + :param value: value to write + + This command generates a :class:`WriteSingleCoil`, + or :class:`WriteSingleRegisterRequest` depending on the address + prefix; 0 or 4. + """ + args = args.split() + if _debug: ConsoleClient._debug("do_read %r", args) + + if (len(args) < 3): + print("address, unit and register required") + return + + # get the address and unit + addr, unitID, register = args[:3] + unitID = int(unitID) + if _debug: ConsoleClient._debug(" - addr, unitID: %r, %r", addr, unitID) + + # get the register and count + register = int(register) + if len(args) == 4: + rcount = int(args[3]) + else: + rcount = 1 + if _debug: ConsoleClient._debug(" - register, rcount: %r, %r", register, rcount) + + # decode the register into a type + digits = int(math.log10(register)) + 1 + if digits < 4: + # must be a coil + registerType = 0 + elif digits == 5: + registerType = register // 10000 + register = register % 10000 + elif digits == 6: + registerType = register // 100000 + register = register % 100000 + else: + print("5 or 6 digit addresses please") + return + if _debug: ConsoleClient._debug(" - registerType, register: %r, %r", registerType, register) + + # build a request + if registerType == 0: + # coil + req = WriteSingleCoilRequest(register - 1, value) + elif registerType == 4: + # holding register + req = WriteSingleRegisterRequest(register - 1, value) + else: + print("unsupported register type") + return + + # set the destination + req.pduDestination = (addr, 502) + req.mpduUnitID = unitID + if _debug: ConsoleClient._debug(" - req: %r", req) + + # save the request + self.req = req + + # send it along + self.request(req) + def confirmation(self, pdu): """Prints out the contents of the response from the device. @@ -129,15 +203,20 @@ class ConsoleClient(ConsoleCmd, Client): if _debug: ConsoleClient._debug("confirmation %r", pdu) + # exceptions if isinstance(pdu, ExceptionResponse): print(ModbusException(pdu.exceptionCode)) + # read responses elif isinstance(pdu, ReadCoilsResponse): print(" ::=" + str(pdu.bits)) elif isinstance(pdu, ReadDiscreteInputsResponse): print(" ::=" + str(pdu.bits)) + elif isinstance(pdu, ReadInputRegistersResponse): + print(" ::=" + str(pdu.registers)) + elif isinstance(pdu, ReadMultipleRegistersResponse): print(" ::=" + str(pdu.registers)) @@ -148,6 +227,13 @@ class ConsoleClient(ConsoleCmd, Client): except Exception as err: if _debug: ConsoleClient._debug("unpack exception %r: %r", codec, err) + # write responses + elif isinstance(pdu, WriteSingleCoilResponse): + print(" ::=" + str(pdu.bits)) + + elif isinstance(pdu, WriteSingleRegisterResponse): + print(" ::=" + str(pdu.bits)) + else: raise TypeError("unsupported response")