Tracker Simulator

Can anybody help me with an example of a tracker simulator that sends parameters from a CSV file to a server via UDP.

The message is HEX. The idea is that the script can read parameters from a csv file, use current date/time and create the string following the next table format. Then send the message and go to the next CSV file line. There must be a delay after every message sent.

Keyword Default Value Bytes Description
OptionsByte 83 1 Indicates the type of data in the message
MobileIDLength 08 1 Length of MobileID in bytes
MobileID "From CSV file" 8 ID of the device that originated the message
MobileIDTypeLen 01 1 Length of the MobileID type
MobileIDType 02 1 Type of identification (IMEI, ESN, etc.)
Service Type 01 1 Type of service for the message
Message Type 02 1 Type of message (event, report, etc.)
Sequence# 0000 2 Sequence number of the message
Update Time "Current Time" 4 Time of message update
Time of Fix "Current Time" 4 Time of the last GPS fix
Latitude "From CSV file" 4 Latitude in decimal degrees
Longitude "From CSV file" 4 Longitude in decimal degrees
Altitude "From CSV file" 4 Altitude in centimeters
Speed "From CSV file" 4 Speed in centimeters per second
Heading "From CSV file" 2 Heading in degrees from true north
Satellites 10 1 Number of satellites used
Fix Status 02 1 GPS fix status
Carrier 0004 2 Network carrier identifier
RSSI FFBF 2 Received signal strength indicator
Comm State 0F 1 Communication modem state
HDOP 00 1 Horizontal dilution of precision
Inputs "From CSV file" 1 Status of digital inputs
Unit Status A1 1 Status of key modules within the unit
Event Index 99 1 Index of the event that generated the report
Event Code 03 1 Event code reported
Accums 06 1 Number of accumulators
Spare 00 1 Reserved space, not used
Accum 0 00000000 4 First accumulator
Accum 1 00000000 4 Second accumulator
Accum 2 10600000 4 Third accumulator
Accum 3 001A35DF 4 Fourth accumulator
Accum 4 02C80269 4 Fifth accumulator
Accum 5 62347EF0 4 Sixth accumulator

An example of the output could be this one:

8308860796050307380F01020102000066BADC8166BADC8105F30E41CE7B98490000000000000000007410020004FFBF0F001Ea199030600000000000000106000000000001A35DF02C8026962347EF0

Thanks.

Here's a script that will open a CSV file, parse it line by line, then prepare and transmit binary packets for each line:

import "io_base.jncx"
import "io_MappedFile.jnc"

enum: uint64_t {
	// epoch difference (in seconds) between Unix time (1 Jan 1970 00:00) and Windows time (1 Jan. 1601 00:00)
	UnixTimeEpochDiff = 11644473600,

	// delay between packets (in milliseconds)
	InterPacketDelay  = 500, 
}

// the structure of the packet

pragma(Alignment, 1)

struct Packet {
	uint8_t m_optionsByte             = 0x83;
	uint8_t m_mobileIdLength          = 0x08;
	bigendian uint64_t m_mobileId;
	uint8_t m_mobileIdTypeLen         = 0x01;
	uint8_t m_mobileIdType            = 0x02;
	uint8_t m_serviceType             = 0x01;
	uint8_t m_messageType             = 0x02;
	bigendian uint16_t m_sequenceIdx;
	bigendian uint32_t m_updateTime;
	bigendian uint32_t m_timeOfFix;
	bigendian uint32_t m_latitude;
	bigendian uint32_t m_longitude;
	bigendian uint32_t m_altitude;
	bigendian uint32_t m_speed;
	bigendian uint16_t m_heading;
	uint8_t m_satellites              = 0x0B;
	uint8_t m_fixStatus               = 0x02;
	bigendian uint16_t m_carrier      = 0x0004;
	bigendian uint16_t m_rssi         = 0xFFBF;
	uint8_t m_commState               = 0x0F;
	uint8_t m_hdop                    = 0x09;
	uint8_t m_inputs;
	uint8_t m_unitStatus              = 0x01;
	uint8_t m_eventIndex              = 0x04;
	uint8_t m_eventCode               = 0xA8;
	uint8_t m_accums                  = 0x06;
	uint8_t m_spare                   = 0x00;
	bigendian uint32_t m_accum0       = 0x00000000;
	bigendian uint32_t m_accum1       = 0x00000000;
	bigendian uint32_t m_accum2       = 0x10600000;
	bigendian uint32_t m_accum3       = 0x001A35DF;
	bigendian uint32_t m_accum4       = 0x02C80269;
	bigendian uint32_t m_accum5       = 0x62347EF0;
	char m_lf                         = '\n';
}

char const* findEol(
	char const* p,
	char const* eof
) {
	char const* eol = memchr(p, '\n', eof - p);
	return eol ? eol + 1 : eof;
}

void main() {
	connect();

	string_t fileName = io.getHomeDir() + "/history.csv"; // adjust accordingly
	io.MappedFile file;
	file.open(fileName, io.FileOpenFlags.ReadOnly);

	size_t size = file.m_size;
	char const* p = file.view(0, size);
	char const* eof = p + size;
	size_t index = 0;

	Packet packet; // all const fields are initialized; we'll adjust variable fields below

	p = findEol(p, eof); // skip the first line
	while (p < eof) { // process the rest line by line	
		char const* eol = findEol(p, eof);
		string_t line(p, eol - p);
		p = eol;
		
		if (line !~ r"\s*([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*)")
			continue; // skip all CSV lines that do not match the pattern

		// Jancy uses Windows timestamps (in 100-nsec intervals, i.e. sec / 10^7)
		uint_t unixTime = sys.getTimestamp() / 10000000 - UnixTimeEpochDiff;		

		// adjust all the variable fields in the packet
		packet.m_mobileId = strtoul($1,, 16);
		packet.m_sequenceIdx = index++;
		packet.m_updateTime = unixTime;
		packet.m_timeOfFix = unixTime;
		packet.m_latitude = (uint_t)(atof($3) * 10000000);
		packet.m_longitude = (uint_t)(atof($4) * 10000000);
		packet.m_altitude = (uint_t)(atof($5) * 100);
		packet.m_speed = (uint_t)(atof($6) * 100);
		packet.m_heading = strtoul($7);
		packet.m_inputs = strtoul($8);

		// transmit, wait and move on to the next line
		transmit(&packet, sizeof(packet));
		sys.sleep(InterPacketDelay); 
	}
}

Unlike the original PHP sample I received from you, I didn't generate a HEX string first -- in Jancy, it's much cleaner (and more efficient, of course) to generate binary data right away. First, we declare the Packet struct according to your specification and initialize all constant fields; then, we walk over the file line by line and adjust fields that depend on the CSV data.

Feel free to ask any questions regarding the script.

This script only generates packet contents and passes the raw data to the underlying session for transmission -- so it will work with any transport. If you need to send those packets over UDP, open the "UDP Socket" plugin, configure remote IP:Port accordingly, then run the script:

8b2ce837-f29d-47ec-ae0e-78923db521f0-image.png

I thought I responded to your answer Vladimir. Thank you for taking the time to create the script. I can tell you that it works perfectly and has saved me a lot of time in testing tasks. By the way, the process is very efficient and precise.