def unit(self, uid): """Return the poller to access data for the given unit uid. Force """ if uid not in self.pollers: self.pollers[uid] = poller_modbus("SMC %s" % (uid), client=self, multi=True, unit=uid, rate=self.rate) return self.pollers[uid]
def main(): parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, epilog = """\ Begin polling the designated register range(s), optionally writing initial values to them. Register range(s) and value(s) must be supplied: <begin>[-<end>] <begin>[-<end>]=<val>,... EXAMPLE modbus_poll --address localhost:7502 40001-40100 """ ) parser.add_argument( '-v', '--verbose', default=0, action="count", help="Display logging information." ) parser.add_argument('-l', '--log', type=str, default=None, help="Direct log output to the specified file" ) parser.add_argument( '-a', '--address', default="0.0.0.0:502", help="Default [interface][:port] to bind to (default: any, port 502)" ) parser.add_argument( '-r', '--reach', default=1, help="Merge polls within <reach> registers of each-other" ) parser.add_argument( '-R', '--rate', default=1.0, help="Target poll rate" ) parser.add_argument( '-t', '--timeout', default=Defaults.Timeout, help="I/O Timeout (default: %s)" % ( Defaults.Timeout )) parser.add_argument( 'registers', nargs="+" ) args = parser.parse_args() # Deduce logging level and target file (if any) levelmap = { 0: logging.WARNING, 1: logging.NORMAL, 2: logging.DETAIL, 3: logging.INFO, 4: logging.DEBUG, } cpppo.log_cfg['level'] = ( levelmap[args.verbose] if args.verbose in levelmap else logging.DEBUG ) if args.log: cpppo.log_cfg['filename'] = args.log logging.basicConfig( **cpppo.log_cfg ) # (INADDR_ANY) if only :port is supplied. Port defaults to 502 if only # interface is supplied. After this block, 'address' is always a tuple # like ("interface",502) address = None if args.address: address = args.address.split(':') assert 1 <= len( address ) <= 2 address = ( str( address[0] ), int( address[1] ) if len( address ) > 1 else Defaults.Port ) log.info( "--address '%s' produces address=%r" % ( args.address, address )) # Set up the Modbus/TCP I/O timeout to use, for all connect and read/write transactions Defaults.Timeout = float( args.timeout ) # Start the PLC poller (and perform any initial writes indicated) poller = poller_modbus( "Modbus/TCP", host=address[0], port=address[1], reach=int( args.reach ), rate=float( args.rate )) for txt in args.registers: beg,end,val = register_decode( txt ) # beg-end is inclusive for reg in range( beg, end+1 ): poller.poll( reg ) if val: # Value(s) were supplied for the register(s) range; write 'em. This results in a # WriteMultipleRegistersRequest if val is an iterable, or a WriteSingle... if not. # We'll need to shatter/merge the register range into appropriate sized chunks for a # valid Modbus/TCP request, and then take the appropriate number of values for each. for base,length in merge( [ (beg,end-beg+1) ] ): poller.write( base, val[0] if length == 1 else val[:length] ) val = val[length:] load = '' fail = '' poll = '' regs = {} while True: loadcur = "%.2f" % ( poller.load[0] if poller.load[0] else 0 ) if loadcur != load: load = loadcur logging.detail( "load: %s", loadcur ) failcur = ", ".join( [ ("%d-%d" % (b,b+c-1)) for b,c in poller.failing ] ) pollcur = ", ".join( [ ("%d-%d" % (b,b+c-1)) for b,c in poller.polling ] ) if ( failcur != fail or pollcur != poll ): fail, poll = failcur, pollcur logging.normal( "failing: %s, polling: %s", fail, poll ) # log data changes for beg,cnt in poller.polling: for reg in range( beg, beg+cnt ): val = poller.read( reg ) old = regs.get( reg ) # may be None if val != old: logging.warning( "%5d == %5d (was: %s)" %( reg, val, old )) regs[reg] = val time.sleep( 1 )
def main(): parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, epilog = """\ Register range(s) and value(s) must be supplied: <begin>[-<end>] EXAMPLE modbus_poll --address localhost:7502 40001-40100 """ ) parser.add_argument( '-v', '--verbose', default=0, action="count", help="Display logging information." ) parser.add_argument('-l', '--log', type=str, default=None, help="Direct log output to the specified file" ) parser.add_argument( '-a', '--address', default="0.0.0.0:502", help="Default [interface][:port] to bind to (default: any, port 502)" ) parser.add_argument( '-r', '--reach', default=1, help="Merge polls within <reach> registers of each-other" ) parser.add_argument( '-R', '--rate', default=1.0, help="Target poll rate" ) parser.add_argument( 'registers', nargs="+" ) args = parser.parse_args() # Deduce logging level and target file (if any) levelmap = { 0: logging.WARNING, 1: logging.NORMAL, 2: logging.DETAIL, 3: logging.INFO, 4: logging.DEBUG, } cpppo.log_cfg['level'] = ( levelmap[args.verbose] if args.verbose in levelmap else logging.DEBUG ) if args.log: cpppo.log_cfg['filename'] = args.log logging.basicConfig( **cpppo.log_cfg ) # (INADDR_ANY) if only :port is supplied. Port defaults to 502 if only # interface is supplied. After this block, 'address' is always a tuple # like ("interface",502) address = None if args.address: address = args.address.split(':') assert 1 <= len( address ) <= 2 address = ( str( address[0] ), int( address[1] ) if len( address ) > 1 else Defaults.Port ) log.info( "--address '%s' produces address=%r" % ( args.address, address )) # Start the PLC poller poller = poller_modbus( "Modbus/TCP", host=address[0], port=address[1], reach=int( args.reach ), rate=float( args.rate )) for r in args.registers: rng = r.split('-') beg,cnt = int(rng[0]), int(rng[1])-int(rng[0])+1 if len(rng) else 1 for reg in range( beg, beg+cnt ): poller.poll( reg ) load = '' fail = '' poll = '' regs = {} while True: loadcur = "%.2f" % ( poller.load[0] if poller.load[0] else 0 ) if loadcur != load: load = loadcur logging.detail( "load: %s", loadcur ) failcur = ", ".join( [ ("%d-%d" % (b,b+c-1)) for b,c in poller.failing ] ) pollcur = ", ".join( [ ("%d-%d" % (b,b+c-1)) for b,c in poller.polling ] ) if ( failcur != fail or pollcur != poll ): fail, poll = failcur, pollcur logging.normal( "failing: %s, polling: %s", fail, poll ) # log data changes for beg,cnt in poller.polling: for reg in range( beg, beg+cnt ): val = poller.read( reg ) old = regs.get( reg ) # may be None if val != old: logging.warning( "%5d == %5d (was: %s)" %( reg, val, old )) regs[reg] = val time.sleep( 1 )
def main(): parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, epilog="""\ Register range(s) and value(s) must be supplied: <begin>[-<end>] EXAMPLE modbus_poll --address localhost:7502 40001-40100 """) parser.add_argument('-v', '--verbose', default=0, action="count", help="Display logging information.") parser.add_argument('-l', '--log', type=str, default=None, help="Direct log output to the specified file") parser.add_argument( '-a', '--address', default="0.0.0.0:502", help="Default [interface][:port] to bind to (default: any, port 502)") parser.add_argument( '-r', '--reach', default=1, help="Merge polls within <reach> registers of each-other") parser.add_argument('-R', '--rate', default=1.0, help="Target poll rate") parser.add_argument('registers', nargs="+") args = parser.parse_args() # Deduce logging level and target file (if any) levelmap = { 0: logging.WARNING, 1: logging.NORMAL, 2: logging.DETAIL, 3: logging.INFO, 4: logging.DEBUG, } cpppo.log_cfg['level'] = (levelmap[args.verbose] if args.verbose in levelmap else logging.DEBUG) if args.log: cpppo.log_cfg['filename'] = args.log logging.basicConfig(**cpppo.log_cfg) # (INADDR_ANY) if only :port is supplied. Port defaults to 502 if only # interface is supplied. After this block, 'address' is always a tuple # like ("interface",502) address = None if args.address: address = args.address.split(':') assert 1 <= len(address) <= 2 address = (str(address[0]), int(address[1]) if len(address) > 1 else Defaults.Port) log.info("--address '%s' produces address=%r" % (args.address, address)) # Start the PLC poller poller = poller_modbus("Modbus/TCP", host=address[0], port=address[1], reach=int(args.reach), rate=float(args.rate)) for r in args.registers: rng = r.split('-') beg, cnt = int( rng[0]), int(rng[1]) - int(rng[0]) + 1 if len(rng) else 1 for reg in range(beg, beg + cnt): poller.poll(reg) load = '' fail = '' poll = '' regs = {} while True: loadcur = "%.2f" % (poller.load[0] if poller.load[0] else 0) if loadcur != load: load = loadcur logging.detail("load: %s", loadcur) failcur = ", ".join([("%d-%d" % (b, b + c - 1)) for b, c in poller.failing]) pollcur = ", ".join([("%d-%d" % (b, b + c - 1)) for b, c in poller.polling]) if (failcur != fail or pollcur != poll): fail, poll = failcur, pollcur logging.normal("failing: %s, polling: %s", fail, poll) # log data changes for beg, cnt in poller.polling: for reg in range(beg, beg + cnt): val = poller.read(reg) old = regs.get(reg) # may be None if val != old: logging.warning("%5d == %5d (was: %s)" % (reg, val, old)) regs[reg] = val time.sleep(1)
def unit( self, uid ): """Return the poller to access data for the given unit uid. Force """ if uid not in self.pollers: self.pollers[uid] = poller_modbus( "SMC %s" % ( uid ), client=self, multi=True, unit=uid, rate=self.rate ) return self.pollers[uid]
def main(): parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, epilog="""\ Begin polling the designated register range(s), optionally writing initial values to them. Register range(s) and value(s) must be supplied: <begin>[-<end>] <begin>[-<end>]=<val>,... EXAMPLE modbus_poll --address localhost:7502 40001-40100 """, ) parser.add_argument("-v", "--verbose", default=0, action="count", help="Display logging information.") parser.add_argument("-l", "--log", type=str, default=None, help="Direct log output to the specified file") parser.add_argument( "-a", "--address", default="0.0.0.0:502", help="Default [interface][:port] to bind to (default: any, port 502)" ) parser.add_argument("-r", "--reach", default=1, help="Merge polls within <reach> registers of each-other") parser.add_argument("-R", "--rate", default=1.0, help="Target poll rate") parser.add_argument( "-t", "--timeout", default=Defaults.Timeout, help="I/O Timeout (default: %s)" % (Defaults.Timeout) ) parser.add_argument("registers", nargs="+") args = parser.parse_args() # Deduce logging level and target file (if any) levelmap = {0: logging.WARNING, 1: logging.NORMAL, 2: logging.DETAIL, 3: logging.INFO, 4: logging.DEBUG} cpppo.log_cfg["level"] = levelmap[args.verbose] if args.verbose in levelmap else logging.DEBUG if args.log: cpppo.log_cfg["filename"] = args.log logging.basicConfig(**cpppo.log_cfg) # (INADDR_ANY) if only :port is supplied. Port defaults to 502 if only # interface is supplied. After this block, 'address' is always a tuple # like ("interface",502) address = None if args.address: address = args.address.split(":") assert 1 <= len(address) <= 2 address = (str(address[0]), int(address[1]) if len(address) > 1 else Defaults.Port) log.info("--address '%s' produces address=%r" % (args.address, address)) # Set up the Modbus/TCP I/O timeout to use, for all connect and read/write transactions Defaults.Timeout = float(args.timeout) # Start the PLC poller (and perform any initial writes indicated) poller = poller_modbus("Modbus/TCP", host=address[0], port=address[1], reach=int(args.reach), rate=float(args.rate)) for txt in args.registers: beg, end, val = register_decode(txt) # beg-end is inclusive for reg in range(beg, end + 1): poller.poll(reg) if val: # Value(s) were supplied for the register(s) range; write 'em. This results in a # WriteMultipleRegistersRequest if val is an iterable, or a WriteSingle... if not. # We'll need to shatter/merge the register range into appropriate sized chunks for a # valid Modbus/TCP request, and then take the appropriate number of values for each. for base, length in merge([(beg, end - beg + 1)]): poller.write(base, val[0] if length == 1 else val[:length]) val = val[length:] load = "" fail = "" poll = "" regs = {} while True: loadcur = "%.2f" % (poller.load[0] if poller.load[0] else 0) if loadcur != load: load = loadcur logging.detail("load: %s", loadcur) failcur = ", ".join([("%d-%d" % (b, b + c - 1)) for b, c in poller.failing]) pollcur = ", ".join([("%d-%d" % (b, b + c - 1)) for b, c in poller.polling]) if failcur != fail or pollcur != poll: fail, poll = failcur, pollcur logging.normal("failing: %s, polling: %s", fail, poll) # log data changes for beg, cnt in poller.polling: for reg in range(beg, beg + cnt): val = poller.read(reg) old = regs.get(reg) # may be None if val != old: logging.warning("%5d == %5d (was: %s)" % (reg, val, old)) regs[reg] = val time.sleep(1)