using BorgCh; using BorgCh.Comm; using BorgCh.Comm.Modbus; using System; public class M3749SetTime { [STAThread] static public void Main( string[] args ) { M3749SetTime c = new M3749SetTime(); c.run( args ); } private Master mb; private byte slave_id; public M3749SetTime() { } public void usage() { Console.WriteLine( "\n" + "usage:\n" + " m3749_set_time.exe serportspec slave_id\n" + "\n" + " serportspec: portname-baudrate-databits-parity-stopbits\n" + " parity: 'N' 'E' 'O'\n" + " stopbits '1' '1.5' '2'\n" + " command: 'holding' 'input'\n" + "\n" + "example:\n" + " m3749_set_time.exe COM1:-115200-8-N-1 1\n" + "" ); } public void run( string[] args ) { if( args.Length != 2 ) { usage(); return; } Logger logger = null; bool rc = true; try { mb = new MasterRtu( args[0], logger ); } catch( Exception ex ) { Console.WriteLine( String.Format( "invalid port spec '{0}':\n {1}", args[0], ex.Message ) ); rc = false; } int slave_id_int; if( !Int32.TryParse( args[1], out slave_id_int ) || slave_id_int < 1 || slave_id_int > 254 ) { Console.WriteLine( String.Format( "invalid slave id '{0}'", args[1] ) ); rc = false; } slave_id = (byte)slave_id_int; if( rc ) { ModbusError err; ushort addr; int count; ushort[] data = new ushort[6]; DateTime dt; // read date/time Console.WriteLine( "\n## read date/time" ); addr = 200; count = 3; err = mb.read_holding_registers( slave_id, addr, data, count ); if( err != ModbusError.OK ) { print_error( err, "reading date/time failed" ); return; } else { Console.WriteLine( "data: {0:X04} {1:X04} {2:X04}", data[0], data[1], data[2] ); dt = data_to_datetime( data ); Console.WriteLine( "date/time was: {0}-{1}-{2} {3}:{4}", dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute ); } // read access level Console.WriteLine( "\n## read access level" ); addr = 3288; count = 2; err = mb.read_holding_registers( slave_id, addr, data, count ); if( err != ModbusError.OK ) { print_error( err, "reading back access level failed" ); return; } Console.WriteLine( "access level: {0:X04} {1:X04}", data[0], data[1] ); // set access level Console.WriteLine( "\n## set access level" ); addr = 3288; count = 4; data[2] = 0x0000; data[3] = 0x000C; data[4] = 0x0114; data[5] = 0x5DEA; Console.WriteLine( "data: {0:X04} {1:X04} {2:X04} {3:X04}", data[2], data[3], data[4], data[5] ); err = mb.write_multiple_registers( slave_id, addr, data, count, 2 ); if( err != ModbusError.OK ) { print_error( err, "setting access level failed" ); return; } // read back access level Console.WriteLine( "\n## read access level" ); addr = 3288; count = 2; err = mb.read_holding_registers( slave_id, addr, data, count ); if( err != ModbusError.OK ) { print_error( err, "reading back access level failed" ); return; } Console.WriteLine( "access level: {0:X04} {1:X04}", data[0], data[1] ); if( data[0] != data[2] || data[1] != data[3] ) { Console.WriteLine( "read back different access level" ); Console.WriteLine( "{0:X04} {1:X04} != {2:X04} {3:X04}", data[0], data[1], data[2], data[3] ); return; } /* // enable writing to EEPROM Console.WriteLine( "\n## enable writing to EEPROM" ); addr = 3999; data[0] = 0x5752; err = mb.write_single_register( slave_id, addr, data[0] ); if( err != ModbusError.OK ) { print_error( err, "enable writing to EEPROM failed" ); return; } */ // set time and date Console.WriteLine( "\n## set date/time" ); dt = DateTime.Now; //dt.Year ^= 1; // dt = new DateTime( dt.Year^1, dt.Month, dt.Day, dt.Hour, dt.Minute, 0 ); addr = 200; count = 3; datetime_to_data( dt, ref data ); // data[0]++; Console.WriteLine( "PC date/time is: {0}-{1}-{2} {3}:{4}", dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute ); Console.WriteLine( "data: {0:X04} {1:X04} {2:X04}", data[0], data[1], data[2] ); err = mb.write_multiple_registers( slave_id, addr, data , count); if( err != ModbusError.OK ) { print_error( err, "setting date/time failed" ); return; } // read date/time Console.WriteLine( "\n## read date/time" ); addr = 200; count = 3; err = mb.read_holding_registers( slave_id, addr, data, count ); if( err != ModbusError.OK ) { print_error( err, "reading date/time failed" ); return; } Console.WriteLine( "data: {0:X04} {1:X04} {2:X04}", data[0], data[1], data[2] ); dt = data_to_datetime( data ); Console.WriteLine( "date/time is now: {0}-{1}-{2} {3}:{4}", dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute ); } } void print_error( ModbusError err, string text ) { Console.WriteLine( text ); int n = (int)err; switch( err ) { case ModbusError.NO_CONNECTION: Console.WriteLine( "{0}: No connection.", n ); break; case ModbusError.INVALID_SLAVE_ID: Console.WriteLine( "{0}: Invalid slave ID.", n ); break; case ModbusError.TOO_FEW_REGISTERS: Console.WriteLine( "{0}: Too few registers requested.", n ); break; case ModbusError.TOO_MANY_REGISTERS: Console.WriteLine( "{0}: Too many registers requested.", n ); break; case ModbusError.INVALID_OFFSET: Console.WriteLine( "{0}: An invalid offset has been specified.", n ); break; case ModbusError.LAST_REG_NR_TOO_HIGH: Console.WriteLine( "{0}: Last register number too high.", n ); break; case ModbusError.SERPORT_OPEN_ERROR: Console.WriteLine( "{0}: Serial port open error.", n ); break; case ModbusError.TCP_CONNECT_ERROR: Console.WriteLine( "{0}: TCP connect error.", n ); break; case ModbusError.SEND_ERROR: Console.WriteLine( "{0}: Send error.", n ); break; case ModbusError.RECV_ERROR: Console.WriteLine( "{0}: Recv error.", n ); break; case ModbusError.RECV_SHORT_REPLY: Console.WriteLine( "{0}: Received short reply.", n ); break; case ModbusError.TIMEOUT: Console.WriteLine( "{0}: Timeout.", n ); break; case ModbusError.UNIT_ID_MISMATCH: Console.WriteLine( "{0}: Unit ID mismatch in reply.", n ); break; case ModbusError.FUNCTION_MISMATCH: Console.WriteLine( "{0}: Function mismatch in reply.", n ); break; case ModbusError.CRC_MISMATCH: Console.WriteLine( "{0}: CRC mismatch in reply.", n ); break; case ModbusError.ILLEGAL_FUNCTION: Console.WriteLine( "{0}: Device replied with 'illegal function'.", n ); break; case ModbusError.ILLEGAL_DATA_ADDRESS: Console.WriteLine( "{0}: Device replied with 'illegal data address'.", n ); break; case ModbusError.ILLEGAL_DATA_VALUE: Console.WriteLine( "{0}: Device replied with 'illegal data value'.", n ); break; case ModbusError.SLAVE_DEVICE_FAILURE: Console.WriteLine( "{0}: Device replied with 'slave device failure'.", n ); break; case ModbusError.SLAVE_DEVICE_BUSY: Console.WriteLine( "{0}: Device replied with 'slave device busy'.", n ); break; case ModbusError.UNKNOWN_SLAVE_ERROR: Console.WriteLine( "{0}: Device replied with an unknown error code.", n ); break; case ModbusError.COMMUNICATION_ERROR: Console.WriteLine( "{0}: Communication error.", n ); break; case ModbusError.INTERNAL_ERROR: Console.WriteLine( "{0}: Internal error.", n ); break; case ModbusError.OK: Console.WriteLine( "{0}: OK", n ); break; default: Console.WriteLine( "{0}: unknown error.", n ); break; } } DateTime data_to_datetime( ushort[] data ) { return new DateTime( from_bcd(data[0])+2000, from_bcd(data[1]>>8), from_bcd(data[1]&0xFF), from_bcd(data[2]>>8), from_bcd(data[2]&0xFF), 0 ); } void datetime_to_data( DateTime t, ref ushort[] data ) { data[0] = (ushort)to_bcd(t.Year-2000); data[1] = (ushort)(to_bcd(t.Month)<<8 | to_bcd(t.Day)); data[2] = (ushort)(to_bcd(t.Hour)<<8 | to_bcd(t.Minute)); } int from_bcd( int d ) { int n = 0; int f = 1; while( d > 0 ) { n += f * (d & 0x0F); d >>= 4; f *= 10; } return n; } int to_bcd( int n ) { int d = 0; int s = 0; while( n > 0 ) { d |= (n % 10) << s; n /= 10; s += 4; } return d; } }