void main( void) { RCONbits.NOT_POR = 1; RCONbits.NOT_RI = 1; Hardware_Initialize(); Initialize_Variables(); /* initialize BACnet Data Link Layer */ dlmstp_set_my_address(42); dlmstp_set_max_info_frames(1); dlmstp_set_max_master(127); RS485_Set_Baud_Rate(38400); dlmstp_init(); /* Handle anything that needs to be done on powerup */ /* Greet the BACnet world! */ Send_I_Am(&Handler_Transmit_Buffer[0]); /* Main loop */ while (TRUE) { RESTART_WDT(); dlmstp_task(); MainTasks(); Global_Int(INT_ENABLED); ENABLE_TIMER4_INT(); } }
static void bacnet_init( void) { #if defined(BACDL_MSTP) RS485_Set_Baud_Rate(38400); dlmstp_set_mac_address(57); dlmstp_set_max_master(127); dlmstp_set_max_info_frames(1); dlmstp_init(NULL); #endif Device_Set_Object_Instance_Number(11111); #ifndef DLMSTP_TEST /* we need to handle who-is to support dynamic device binding */ apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is); /* Set the handlers for any confirmed services that we support. */ /* We must implement read property - it's required! */ apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY, handler_read_property); apdu_set_confirmed_handler(SERVICE_CONFIRMED_REINITIALIZE_DEVICE, handler_reinitialize_device); apdu_set_confirmed_handler(SERVICE_CONFIRMED_WRITE_PROPERTY, handler_write_property); /* handle communication so we can shutup when asked */ apdu_set_confirmed_handler(SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL, handler_device_communication_control); #endif }
int main( void) { unsigned i = 0; uint8_t DataRegister; RS485_Set_Baud_Rate(38400); RS485_Initialize(); /* receive task */ for (;;) { if (RS485_ReceiveError()) { fprintf(stderr, "ERROR "); } else if (RS485_DataAvailable(&DataRegister)) { fprintf(stderr, "%02X ", DataRegister); } } }
int main( int argc, char *argv[]) { unsigned long hThread = 0; uint32_t arg_value = 0; char lpBuf[1]; DWORD dwRead = 0; unsigned i = 0, len = 0, count = 0; char hex_pair[5] = "0xff"; char ch = ' '; int lsb = 0, msb = 0; long my_baud = 38400; uint8_t buffer[501] = { 0 }; if (argc > 1) { RS485_Set_Interface(argv[1]); } if (argc > 2) { my_baud = strtol(argv[2], NULL, 0); } RS485_Set_Baud_Rate(my_baud); RS485_Initialize(); #if defined(_WIN32) SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), ENABLE_PROCESSED_INPUT); SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlCHandler, TRUE); #endif #ifdef TEST_RS485_TRANSMIT /* read a stream of characters from stdin or argument */ if (argc > 3) { len = strlen(argv[3]); for (i = 0; i < len; i++) { /* grab pairs of hex characters, skip spaces */ ch = argv[3][i]; if (ch == ' ') { continue; } msb = ascii_hex_to_int(ch); if (msb >= 0) { i++; ch = argv[3][i]; lsb = ascii_hex_to_int(ch); if (lsb >= 0) { buffer[count] = msb << 4 | lsb; } else { buffer[count] = msb; } count++; if (count >= sizeof(buffer)) { break; } } } RS485_Send_Frame(NULL, buffer, count); } #endif #ifdef TEST_RS485_RECEIVE /* receive task */ for (;;) { if (!ReadFile(RS485_Handle, lpBuf, sizeof(lpBuf), &dwRead, NULL)) { if (GetLastError() != ERROR_IO_PENDING) { RS485_Print_Error(); } } else { /* print any characters received */ if (dwRead) { for (i = 0; i < dwRead; i++) { fprintf(stderr, "%02X ", lpBuf[i]); } } dwRead = 0; } } #endif }
/**************************************************************************** * DESCRIPTION: Reinitializes the port * RETURN: none * ALGORITHM: none * NOTES: none *****************************************************************************/ void RS485_Reinit( void) { RS485_Set_Baud_Rate(38400); }
/**************************************************************************** * DESCRIPTION: Initializes the RS485 hardware and variables, and starts in * receive mode. * RETURN: none * ALGORITHM: none * NOTES: none *****************************************************************************/ void RS485_Initialize_Port( void) { /* Reset USART registers to POR state */ TXSTA2 = 0; RCSTA2 = 0; /* configure USART for receiving */ /* since the TX will handle setting up for transmit */ RCSTA2bits.CREN = 1; /* Interrupt on receipt */ PIE3bits.RC2IE = 1; /* enable the transmitter, disable its interrupt */ TXSTA2bits.TXEN = 1; PIE3bits.TX2IE = 0; /* setup USART Baud Rate Generator */ /* see BAUD RATES FOR ASYNCHRONOUS MODE in Data Book */ /* Fosc=20MHz BRGH=1 BRGH=0 Rate SPBRG Rate SPBRG ------- ----- ------- ----- 9615 129 9469 32 19230 64 19530 15 37878 32 78130 3 56818 21 104200 2 113630 10 312500 0 250000 4 625000 1 1250000 0 */ switch (RS485_Baud_Rate) { case 19200: SPBRG2 = 64; TXSTA2bits.BRGH = 1; break; case 38400: SPBRG2 = 32; TXSTA2bits.BRGH = 1; break; case 57600: SPBRG2 = 21; TXSTA2bits.BRGH = 1; break; case 76800: SPBRG2 = 3; TXSTA2bits.BRGH = 0; break; case 115200: SPBRG2 = 10; TXSTA2bits.BRGH = 1; break; case 9600: SPBRG2 = 129; TXSTA2bits.BRGH = 1; break; default: SPBRG2 = 129; TXSTA2bits.BRGH = 1; RS485_Set_Baud_Rate(9600); break; } /* select async mode */ TXSTA2bits.SYNC = 0; /* enable transmitter */ TXSTA2bits.TXEN = 1; /* serial port enable */ RCSTA2bits.SPEN = 1; /* since we are using RS485, we need to explicitly say transmit enable or not */ RS485_RX_DISABLE = 0; RS485_TX_ENABLE = 0; }
bool Device_Write_Property( BACNET_WRITE_PROPERTY_DATA * wp_data, BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code) { bool status = false; /* return value */ int len = 0; BACNET_APPLICATION_DATA_VALUE value; if (!Device_Valid_Object_Instance_Number(wp_data->object_instance)) { *error_class = ERROR_CLASS_OBJECT; *error_code = ERROR_CODE_UNKNOWN_OBJECT; return false; } /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, wp_data->application_data_len, &value); /* FIXME: len < application_data_len: more data? */ /* FIXME: len == 0: unable to decode? */ switch (wp_data->object_property) { case PROP_OBJECT_IDENTIFIER: if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) { if ((value.type.Object_Id.type == OBJECT_DEVICE) && (Device_Set_Object_Instance_Number(value.type. Object_Id.instance))) { /* we could send an I-Am broadcast to let the world know */ status = true; } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_MAX_INFO_FRAMES: if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if (value.type.Unsigned_Int <= 255) { dlmstp_set_max_info_frames(value.type.Unsigned_Int); status = true; } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_MAX_MASTER: if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if ((value.type.Unsigned_Int > 0) && (value.type.Unsigned_Int <= 127)) { dlmstp_set_max_master(value.type.Unsigned_Int); status = true; } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_OBJECT_NAME: if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) { uint8_t encoding; encoding = characterstring_encoding(&value.type.Character_String); if (encoding == CHARACTER_ANSI_X34) { if (characterstring_ansi_copy(&Object_Name[0], sizeof(Object_Name), &value.type.Character_String)) { status = true; } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY; } } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED; } } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case 9600: if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if (value.type.Unsigned_Int > 115200) { RS485_Set_Baud_Rate(value.type.Unsigned_Int); status = true; } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; default: *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; } return status; }
/* simple test to packetize the data and print it */ int main( int argc, char *argv[]) { volatile struct mstp_port_struct_t *mstp_port; long my_baud = 38400; uint32_t packet_count = 0; MSTP_Port.InputBuffer = &RxBuffer[0]; MSTP_Port.InputBufferSize = sizeof(RxBuffer); MSTP_Port.OutputBuffer = &TxBuffer[0]; MSTP_Port.OutputBufferSize = sizeof(TxBuffer); MSTP_Port.This_Station = 127; MSTP_Port.Nmax_info_frames = 1; MSTP_Port.Nmax_master = 127; MSTP_Port.SilenceTimer = Timer_Silence; MSTP_Port.SilenceTimerReset = Timer_Silence_Reset; /* mimic our pointer in the state machine */ mstp_port = &MSTP_Port; MSTP_Init(mstp_port); packet_statistics_clear(); /* initialize our interface */ if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) { printf("mstpcap --scan <filename>\r\n" "perform statistic analysis on MS/TP capture file.\r\n"); printf("\r\n"); printf("mstpcap [interface] [baud] [named pipe]\r\n" "Captures MS/TP packets from a serial interface\r\n" "and save them to a file. Saves packets in a\r\n" "filename mstp_20090123091200.cap that has data and time.\r\n" "After receiving 65535 packets, a new file is created.\r\n" "\r\n" "Command line options:\r\n" "[interface] - serial interface.\r\n" " defaults to COM4 on Windows, and /dev/ttyUSB0 on linux.\r\n" "[baud] - baud rate. 9600, 19200, 38400, 57600, 115200\r\n" " defaults to 38400.\r\n" "[named pipe] - use \\\\.\\pipe\\wireshark as the name\r\n" " and set that name as the interface name in Wireshark\r\n"); return 0; } if ((argc > 1) && (strcmp(argv[1], "--version") == 0)) { printf("mstpcap %s\r\n", BACNET_VERSION_TEXT); printf("Copyright (C) 2011 by Steve Karg\r\n" "This is free software; see the source for copying conditions.\r\n" "There is NO warranty; not even for MERCHANTABILITY or\r\n" "FITNESS FOR A PARTICULAR PURPOSE.\r\n"); return 0; } if ((argc > 1) && (strcmp(argv[1], "--scan") == 0)) { if (argc > 2) { printf("Scanning %s\r\n", argv[2]); /* perform statistics on the file */ if (test_global_header(argv[2])) { while (read_received_packet(mstp_port)) { packet_count++; fprintf(stderr, "\r%u packets", (unsigned) packet_count); } if (packet_count) { packet_statistics_print(); } } else { fprintf(stderr, "File header does not match.\n"); } return 1; } } if (argc > 1) { RS485_Set_Interface(argv[1]); } else { #if defined(_WIN32) print_com_ports(); return 0; #endif } if (argc > 2) { my_baud = strtol(argv[2], NULL, 0); RS485_Set_Baud_Rate(my_baud); } atexit(cleanup); RS485_Initialize(); timer_init(); fprintf(stdout, "mstpcap: Using %s for capture at %ld bps.\n", RS485_Interface(), (long) RS485_Get_Baud_Rate()); #if defined(_WIN32) SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), ENABLE_PROCESSED_INPUT); SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlCHandler, TRUE); #else signal_init(); #endif if (argc > 3) { named_pipe_create(argv[3]); } filename_create_new(); /* run forever */ for (;;) { RS485_Check_UART_Data(mstp_port); MSTP_Receive_Frame_FSM(mstp_port); /* process the data portion of the frame */ if (mstp_port->ReceivedValidFrame) { write_received_packet(mstp_port); mstp_port->ReceivedValidFrame = false; packet_count++; } else if (mstp_port->ReceivedValidFrameNotForUs) { write_received_packet(mstp_port); mstp_port->ReceivedValidFrameNotForUs = false; packet_count++; } else if (mstp_port->ReceivedInvalidFrame) { write_received_packet(mstp_port); Invalid_Frame_Count++; mstp_port->ReceivedInvalidFrame = false; packet_count++; } if (!(packet_count % 100)) { fprintf(stdout, "\r%hu packets, %hu invalid frames", packet_count, Invalid_Frame_Count); } if (packet_count >= 65535) { packet_statistics_print(); packet_statistics_clear(); filename_create_new(); packet_count = 0; } } }
bool Device_Write_Property_Local( BACNET_WRITE_PROPERTY_DATA * wp_data) { bool status = false; /* return value - false=error */ int len = 0; uint8_t encoding = 0; size_t length = 0; BACNET_APPLICATION_DATA_VALUE value; /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, wp_data->application_data_len, &value); /* FIXME: len < application_data_len: more data? */ if (len < 0) { /* error while decoding - a value larger than we can handle */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; return false; } if ((wp_data->object_property != PROP_OBJECT_LIST) && (wp_data->array_index != BACNET_ARRAY_ALL)) { /* only array properties can have array options */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; return false; } switch ((int) wp_data->object_property) { case PROP_OBJECT_IDENTIFIER: if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) { if ((value.type.Object_Id.type == OBJECT_DEVICE) && (Device_Set_Object_Instance_Number(value.type. Object_Id.instance))) { /* we could send an I-Am broadcast to let the world know */ status = true; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_MAX_INFO_FRAMES: if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if (value.type.Unsigned_Int <= 255) { dlmstp_set_max_info_frames(value.type.Unsigned_Int); status = true; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_MAX_MASTER: if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if ((value.type.Unsigned_Int > 0) && (value.type.Unsigned_Int <= 127)) { dlmstp_set_max_master(value.type.Unsigned_Int); status = true; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_OBJECT_NAME: if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) { length = characterstring_length(&value.type.Character_String); if (length < 1) { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } else if (length < characterstring_capacity(&My_Object_Name)) { encoding = characterstring_encoding(&value.type.Character_String); if (encoding < MAX_CHARACTER_STRING_ENCODING) { /* All the object names in a device must be unique. */ if (Device_Valid_Object_Name(&value.type. Character_String, NULL, NULL)) { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_DUPLICATE_NAME; } else { Device_Set_Object_Name(&value.type. Character_String); status = true; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case 9600: if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if (value.type.Unsigned_Int <= 115200) { RS485_Set_Baud_Rate(value.type.Unsigned_Int); status = true; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_NUMBER_OF_APDU_RETRIES: case PROP_APDU_TIMEOUT: case PROP_VENDOR_IDENTIFIER: case PROP_SYSTEM_STATUS: case PROP_LOCATION: case PROP_DESCRIPTION: case PROP_MODEL_NAME: case PROP_VENDOR_NAME: case PROP_FIRMWARE_REVISION: case PROP_APPLICATION_SOFTWARE_VERSION: case PROP_LOCAL_TIME: case PROP_UTC_OFFSET: case PROP_LOCAL_DATE: case PROP_DAYLIGHT_SAVINGS_STATUS: case PROP_PROTOCOL_VERSION: case PROP_PROTOCOL_REVISION: case PROP_PROTOCOL_SERVICES_SUPPORTED: case PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED: case PROP_OBJECT_LIST: case PROP_MAX_APDU_LENGTH_ACCEPTED: case PROP_SEGMENTATION_SUPPORTED: case PROP_DEVICE_ADDRESS_BINDING: case PROP_DATABASE_REVISION: case PROP_ACTIVE_COV_SUBSCRIPTIONS: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; default: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY; break; } /* not using len at this time */ len = len; return status; }
/* simple test to packetize the data and print it */ int main( int argc, char *argv[]) { volatile struct mstp_port_struct_t *mstp_port; long my_baud = 38400; uint32_t packet_count = 0; #if defined(_WIN32) unsigned long hThread = 0; uint32_t arg_value = 0; #else int rc = 0; pthread_t hThread; #endif int sockfd = -1; char *my_interface = "eth0"; /* mimic our pointer in the state machine */ mstp_port = &MSTP_Port; if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) { printf("mstsnap [serial] [baud] [network]\r\n" "Captures MS/TP packets from a serial interface\r\n" "and sends them to a network interface using SNAP \r\n" "protocol packets (mimics Cimetrics U+4 packet).\r\n" "\r\n" "Command line options:\r\n" "[serial] - serial interface.\r\n" " defaults to /dev/ttyUSB0.\r\n" "[baud] - baud rate. 9600, 19200, 38400, 57600, 115200\r\n" " defaults to 38400.\r\n" "[network] - network interface.\r\n" " defaults to eth0.\r\n" ""); return 0; } /* initialize our interface */ if (argc > 1) { RS485_Set_Interface(argv[1]); } if (argc > 2) { my_baud = strtol(argv[2], NULL, 0); } if (argc > 3) { my_interface = argv[3]; } sockfd = network_init(my_interface, ETH_P_ALL); if (sockfd == -1) { return 1; } RS485_Set_Baud_Rate(my_baud); RS485_Initialize(); MSTP_Port.InputBuffer = &RxBuffer[0]; MSTP_Port.InputBufferSize = sizeof(RxBuffer); MSTP_Port.OutputBuffer = &TxBuffer[0]; MSTP_Port.OutputBufferSize = sizeof(TxBuffer); MSTP_Port.This_Station = 127; MSTP_Port.Nmax_info_frames = 1; MSTP_Port.Nmax_master = 127; MSTP_Port.SilenceTimer = Timer_Silence; MSTP_Port.SilenceTimerReset = Timer_Silence_Reset; MSTP_Init(mstp_port); mstp_port->Lurking = true; fprintf(stdout, "mstpcap: Using %s for capture at %ld bps.\n", RS485_Interface(), (long) RS485_Get_Baud_Rate()); #if defined(_WIN32) hThread = _beginthread(milliseconds_task, 4096, &arg_value); if (hThread == 0) { fprintf(stderr, "Failed to start timer task\n"); } (void) SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); #else /* start our MilliSec task */ rc = pthread_create(&hThread, NULL, milliseconds_task, NULL); signal_init(); #endif atexit(cleanup); /* run forever */ for (;;) { RS485_Check_UART_Data(mstp_port); MSTP_Receive_Frame_FSM(mstp_port); /* process the data portion of the frame */ if (mstp_port->ReceivedValidFrame) { mstp_port->ReceivedValidFrame = false; snap_received_packet(mstp_port, sockfd); packet_count++; } else if (mstp_port->ReceivedInvalidFrame) { mstp_port->ReceivedInvalidFrame = false; fprintf(stderr, "ReceivedInvalidFrame\n"); snap_received_packet(mstp_port, sockfd); packet_count++; } if (!(packet_count % 100)) { fprintf(stdout, "\r%hu packets", packet_count); } } return 0; }
/* simple test to packetize the data and print it */ int main( int argc, char *argv[]) { volatile struct mstp_port_struct_t *mstp_port; long my_baud = 38400; uint32_t packet_count = 0; int sockfd = -1; char *my_interface = "eth0"; /* mimic our pointer in the state machine */ mstp_port = &MSTP_Port; if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) { printf("mstsnap [serial] [baud] [network]\r\n" "Captures MS/TP packets from a serial interface\r\n" "and sends them to a network interface using SNAP \r\n" "protocol packets (mimics Cimetrics U+4 packet).\r\n" "\r\n" "Command line options:\r\n" "[serial] - serial interface.\r\n" " defaults to /dev/ttyUSB0.\r\n" "[baud] - baud rate. 9600, 19200, 38400, 57600, 115200\r\n" " defaults to 38400.\r\n" "[network] - network interface.\r\n" " defaults to eth0.\r\n" ""); return 0; } /* initialize our interface */ if (argc > 1) { RS485_Set_Interface(argv[1]); } if (argc > 2) { my_baud = strtol(argv[2], NULL, 0); } if (argc > 3) { my_interface = argv[3]; } sockfd = network_init(my_interface, ETH_P_ALL); if (sockfd == -1) { return 1; } RS485_Set_Baud_Rate(my_baud); RS485_Initialize(); MSTP_Port.InputBuffer = &RxBuffer[0]; MSTP_Port.InputBufferSize = sizeof(RxBuffer); MSTP_Port.OutputBuffer = &TxBuffer[0]; MSTP_Port.OutputBufferSize = sizeof(TxBuffer); MSTP_Port.This_Station = 127; MSTP_Port.Nmax_info_frames = 1; MSTP_Port.Nmax_master = 127; MSTP_Port.SilenceTimer = Timer_Silence; MSTP_Port.SilenceTimerReset = Timer_Silence_Reset; MSTP_Init(mstp_port); fprintf(stdout, "mstpcap: Using %s for capture at %ld bps.\n", RS485_Interface(), (long) RS485_Get_Baud_Rate()); atexit(cleanup); #if defined(_WIN32) SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), ENABLE_PROCESSED_INPUT); SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlCHandler, TRUE); #else signal_init(); #endif /* run forever */ for (;;) { RS485_Check_UART_Data(mstp_port); MSTP_Receive_Frame_FSM(mstp_port); /* process the data portion of the frame */ if (mstp_port->ReceivedValidFrame) { mstp_port->ReceivedValidFrame = false; snap_received_packet(mstp_port, sockfd); packet_count++; } else if (mstp_port->ReceivedInvalidFrame) { mstp_port->ReceivedInvalidFrame = false; fprintf(stderr, "ReceivedInvalidFrame\n"); snap_received_packet(mstp_port, sockfd); packet_count++; } if (!(packet_count % 100)) { fprintf(stdout, "\r%hu packets", packet_count); } } return 0; }
/* simple test to packetize the data and print it */ int main( int argc, char *argv[]) { volatile struct mstp_port_struct_t *mstp_port; long my_baud = 38400; uint32_t packet_count = 0; int argi = 0; char *filename = NULL; MSTP_Port.InputBuffer = &RxBuffer[0]; MSTP_Port.InputBufferSize = sizeof(RxBuffer); MSTP_Port.OutputBuffer = &TxBuffer[0]; MSTP_Port.OutputBufferSize = sizeof(TxBuffer); MSTP_Port.This_Station = 127; MSTP_Port.Nmax_info_frames = 1; MSTP_Port.Nmax_master = 127; MSTP_Port.SilenceTimer = Timer_Silence; MSTP_Port.SilenceTimerReset = Timer_Silence_Reset; /* mimic our pointer in the state machine */ mstp_port = &MSTP_Port; MSTP_Init(mstp_port); packet_statistics_clear(); /* decode any command line parameters */ filename = filename_remove_path(argv[0]); for (argi = 1; argi < argc; argi++) { if (strcmp(argv[argi], "--help") == 0) { print_usage(filename); print_help(filename); return 0; } if (strcmp(argv[argi], "--version") == 0) { printf("mstpcap %s\n", BACNET_VERSION_TEXT); printf("Copyright (C) 2011 by Steve Karg\n" "This is free software; see the source for copying conditions.\n" "There is NO warranty; not even for MERCHANTABILITY or\n" "FITNESS FOR A PARTICULAR PURPOSE.\n"); return 0; } if (strcmp(argv[argi], "--scan") == 0) { argi++; if (argi >= argc) { printf("An file name must be provided.\n"); return 1; } printf("Scanning %s\n", argv[argi]); /* perform statistics on the file */ if (test_global_header(argv[argi])) { while (read_received_packet(mstp_port)) { packet_count++; fprintf(stderr, "\r%u packets", (unsigned) packet_count); } if (packet_count) { packet_statistics_print(); } } else { fprintf(stderr, "File header does not match.\n"); } } if (strcmp(argv[argi], "--extcap-interfaces") == 0) { RS485_Print_Ports(); return 0; } if (strcmp(argv[argi], "--extcap-dlts") == 0) { argi++; if (argi >= argc) { printf("An interface must be provided.\n"); return 0; } printf("dlt {number=%u}{name=BACnet MS/TP}" "{display=BACnet MS/TP}\n", DLT_BACNET_MS_TP); Exit_Requested = true; } if (strcmp(argv[argi], "--extcap-config") == 0) { printf("arg {number=0}{call=--baud}{display=Baud Rate}" "{tooltip=Serial port baud rate in bits per second}" "{type=selector}\n"); printf("value {arg=0}{value=9600}{display=9600}{default=false}\n"); printf("value {arg=0}{value=19200}{display=19200}{default=false}\n"); printf("value {arg=0}{value=38400}{display=38400}{default=true}\n"); printf("value {arg=0}{value=57600}{display=57600}{default=false}\n"); printf("value {arg=0}{value=76800}{display=76800}{default=false}\n"); printf("value {arg=0}{value=115200}{display=115200}{default=false}\n"); return 0; } if (strcmp(argv[argi], "--capture") == 0) { /* do nothing - fall through and start running! */ } if (strcmp(argv[argi], "--extcap-interface") == 0) { argi++; if (argi >= argc) { printf("An interface must be provided or " "the selection must be displayed.\n"); return 0; } RS485_Set_Interface(argv[argi]); } if (strcmp(argv[argi], "--baud") == 0) { argi++; if (argi >= argc) { printf("A baud rate must be provided.\n"); return 0; } my_baud = strtol(argv[argi], NULL, 0); RS485_Set_Baud_Rate(my_baud); } if (strcmp(argv[argi], "--fifo") == 0) { argi++; if (argi >= argc) { printf("A named pipe must be provided.\n"); return 0; } named_pipe_create(argv[argi]); } } if (Exit_Requested) { return 0; } if (argc <= 1) { RS485_Print_Ports(); return 0; } atexit(cleanup); RS485_Initialize(); timer_init(); fprintf(stdout, "mstpcap: Using %s for capture at %ld bps.\n", RS485_Interface(), (long) RS485_Get_Baud_Rate()); #if defined(_WIN32) SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), ENABLE_PROCESSED_INPUT); SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlCHandler, TRUE); #else signal_init(); #endif filename_create_new(); /* run forever */ for (;;) { RS485_Check_UART_Data(mstp_port); MSTP_Receive_Frame_FSM(mstp_port); /* process the data portion of the frame */ if (mstp_port->ReceivedValidFrame) { write_received_packet(mstp_port); mstp_port->ReceivedValidFrame = false; packet_count++; } else if (mstp_port->ReceivedValidFrameNotForUs) { write_received_packet(mstp_port); mstp_port->ReceivedValidFrameNotForUs = false; packet_count++; } else if (mstp_port->ReceivedInvalidFrame) { write_received_packet(mstp_port); Invalid_Frame_Count++; mstp_port->ReceivedInvalidFrame = false; packet_count++; } if (!(packet_count % 100)) { fprintf(stdout, "\r%hu packets, %hu invalid frames", packet_count, Invalid_Frame_Count); } if (packet_count >= 65535) { packet_statistics_print(); packet_statistics_clear(); filename_create_new(); packet_count = 0; } if (Exit_Requested) { break; } } /* tell signal interrupts we are done */ Exit_Requested = false; return 0; }
/* RS485 Baud Rate 9600, 19200, 38400, 57600, 115200 */ void dlmstp_set_baud_rate( uint32_t baud) { RS485_Set_Baud_Rate(baud); }