Esempio n. 1
0
int main(int argc, char* argv[])
{
	fd_set rfds, wfds, efds;
	struct timeval tv;
	int i;
	int tun_fd = -1, tty_fd = -1, serialPortFd = -1;
	int nread, nwrite, pid, retVal, nfds = 0;
	int sync_counter = 0;
	int sync_passed = 0;
	long baud;
	long tx_message_interval;
	long tx_predelay;
	long tx_postdelay;
	long max_allowed_tx_interval;
	unsigned char read_buffer[8192];
	unsigned char extraction_buffer[8192];
	unsigned int extraction_index = 0;
	unsigned char* manchester_buffer = NULL;
	unsigned int manchester_buffer_size;
	unsigned char* ax25_buffer = NULL;
	unsigned int ax25_buffer_size;
	unsigned int frame_length;
	char serial_device[64];
	char tun_name[IFNAMSIZ];
	char subnet[24];
	char ax25_destination[7];
	time_t last_transmission_time;
	time_t last_reception_time;

	if(argc < 2) {
		usage();
		exit(0);
	}

	if(!strcmp("uhf", argv[1]))
	{
		openLogFile(UHF_LOGFILE_NAME);
		baud = RADIOTUNNEL_BIM2A_DEFAULT_BAUD_RATE;
		tx_predelay = RADIOTUNNEL_BIM2A_TX_PREDELAY;
		tx_postdelay = RADIOTUNNEL_BIM2A_TX_POSTDELAY;
		max_allowed_tx_interval = RADIOTUNNEL_BIM2A_MAX_ALLOWED_TRANSMISSION_TIME;
		tx_message_interval = RADIOTUNNEL_BIM2A_TX_MESSAGE_INTERVAL;
	}
	else if(!strcmp("vhf", argv[1]))
	{
		openLogFile(VHF_LOGFILE_NAME);
		baud = RADIOTUNNEL_UHX1_DEFAULT_BAUD_RATE;
		tx_predelay = RADIOTUNNEL_UHX1_TX_PREDELAY;
		tx_postdelay = RADIOTUNNEL_UHX1_TX_POSTDELAY;
		max_allowed_tx_interval = RADIOTUNNEL_UHX1_MAX_ALLOWED_TRANSMISSION_TIME;
		tx_message_interval = RADIOTUNNEL_UHX1_TX_MESSAGE_INTERVAL;
	}
	else
	{
		usage();
		printf("\nwrong invocation!\n");
		exit(0);
	}


	if (argc < 3)
		strcpy(tun_name, IF_NAME);
	else
		strcpy(tun_name, argv[2]);

	if(argc < 4)
		strcpy(subnet, IF_SUBNET);
	else
		strcpy(subnet, argv[3]);

	if (argc < 5)
		strcpy(my_ax25_callsign, nocall_callsign);
	else
		strcpy(my_ax25_callsign, argv[4]);
		my_ax25_callsign[6]=atoi(argv[4]+6);

	if (argc < 6)
		strcpy(serial_device, "/dev/ttyUSB0");
	else
		strcpy(serial_device, argv[5]);

	if(argc < 7)
		ax25_get_broadcast_callsign(ax25_destination);
	else
	{
		strncpy(ax25_destination, argv[6], 6);
		ax25_destination[6]=atoi(argv[6]+6);
	}

	serialPortFd = serial_openSerialPort(serial_device, baud, tx_predelay, tx_postdelay);
	if (serialPortFd < 0)
	{
		perror("serial_openSerialPort()");
		exit(EXIT_FAILURE);
	}
	else
	{
		printf("Opened serial device \'%s\'\n", serial_device);
	}

	tun_fd = tun_alloc(tun_name, IFF_TUN | IFF_NO_PI);
	if (tun_fd < 0)
	{
		perror("tun_alloc()");
		exit(EXIT_FAILURE);
	}
	else
	{
		printf("Interface \'%s\' allocated\n", tun_name);
	}

	tty_fd = open("/dev/tty", O_RDONLY | O_NOCTTY);
	if (tty_fd < 0)
	{
		perror("open tty");
		exit(EXIT_FAILURE);
	}
	else
	{
		printf("/dev/tty opened\n");
	}

	pid = fork();
	if (pid == 0) //if child process
	{
		printf("Starting the interface \'%s\' with address and subnet %s\n", tun_name, subnet);
		if (execlp("ifconfig", " ", tun_name, subnet, "mtu", IF_MTU, "txqueuelen", IF_QUEUE_LENGTH "up", NULL))
			perror("interface up");
		exit(EXIT_FAILURE);
	}

	ax25_initialize_network(my_ax25_callsign);
	time(&last_transmission_time);
	time(&last_reception_time);
	serial_setRTS(0);

	while (1)
	{
		FD_ZERO(&rfds);
		FD_ZERO(&wfds);
		FD_ZERO(&efds);
		FD_SET(serialPortFd, &rfds);
		FD_SET(tun_fd, &rfds);
		FD_SET(tty_fd, &rfds);
		nfds = max(nfds, serialPortFd);
		nfds = max(nfds, tun_fd);
		nfds = max(nfds, tty_fd);
		tv.tv_sec = 5;
		tv.tv_usec = 0;
		retVal = select(nfds + 1, &rfds, &wfds, &efds, NULL/*&tv*/);
		if (retVal < 0 && errno == EINTR)
		{
			continue;
		}
		if (retVal < 0)
		{
			perror("select()");
			exit(EXIT_FAILURE);
		}
		//TTY INTERFACE
		if (FD_ISSET(tty_fd, &rfds))
		{
			nread = read(tty_fd, read_buffer, sizeof(read_buffer));
			printf("Read %d bytes from device fd=%d\n", nread, tty_fd);
			for (i = 0; i < nread; i++)
			{
				if (read_buffer[i] == 0x1b) /*esc*/
					exit(EXIT_SUCCESS);
				putchar(read_buffer[i]);
			}
		}
		//SERIAL PORT
		if (FD_ISSET(serialPortFd, &rfds))
		{
			if ((nread = read(serialPortFd, read_buffer, sizeof(read_buffer))) > 0)
			{
				//printf("# of bytes read = %d\n", nread);
				for (i = 0; i < nread; i++)
				{
					//printf("0x%02x\n",read_buffer[i]);
					if (sync_counter < SYNC_LENGTH && read_buffer[i] == syncword[sync_counter])
					{
						sync_counter++; /* sync continued */
						//printf("sync counting %d\n", sync_counter);
					}
					else
					{
						//printf("sync reset %d -> 0x%02x 0x%02x 0x%02x 0x%02x\n", sync_counter, syncword[0], syncword[1], syncword[2], syncword[3]);
						sync_counter = 0; /* not a preamble, reset counter */
					}
					if (sync_counter >= SYNC_LENGTH && sync_passed == 0)
					{
						sync_passed = 1;
						//printf("sync_passed\n");
					}
					else if (sync_passed)
					{
						time(&last_reception_time);
						//printf("getting data '%c'\n", io[i]);
						if (read_buffer[i] == END_OF_FILE && !isManchester_encoded(read_buffer[i]))
						{
//							printf("non-manchester character received\n");
							manchester_buffer = malloc((extraction_index/2)+1);
							if(manchester_buffer == NULL)
							{
								perror("manchester_buffer malloc()");
							}
							frame_length = manchester_decode(extraction_buffer, manchester_buffer, extraction_index);
//							printf("MANCHESTER DECODED\n");
//							printAsciiHex(manchester_buffer, frame_length);
							ax25_buffer = malloc(frame_length+1);
							if(ax25_buffer == NULL)
							{
								if(manchester_buffer)
								{
									free(manchester_buffer);
									manchester_buffer=NULL;
								}
								perror("ax25_buffer malloc()");
							}
							frame_length = ax25_open_ui_packet(NULL, NULL, ax25_buffer, manchester_buffer, frame_length);
							if (frame_length)
							{
								printf("Read %d bytes from device %s\n", frame_length, serial_device);
								printAsciiHex(ax25_buffer, frame_length);
								registerEvent("RX","");
								nwrite = write(tun_fd, ax25_buffer, frame_length);
								if(nwrite < 0)
								{
									perror("error writing to tun device");
								}
							}
							else
							{
								printf("!ax.25 discarded!\n");
								registerEvent("Discard","RX");
							}
							if(ax25_buffer)
							{
								free(ax25_buffer);
								ax25_buffer = NULL;
							}
							if(manchester_buffer)
							{
								free(manchester_buffer);
								manchester_buffer = NULL;
							}
							sync_passed = 0;
							sync_counter = 0;
							extraction_index = 0;
						}
						else
						{
							//printf("saved data '%c'\n", io[i]);
//							printf("save_index=%d/%d\n",save_index, sizeof(buf));
							if (extraction_index >= sizeof(extraction_buffer))
							{
								sync_passed = 0;
								sync_counter = 0;
								extraction_index = 0;
							}
							else
							{
								extraction_buffer[extraction_index++] = read_buffer[i];
								extraction_buffer[extraction_index + 1] = 0;
							}
							//printf("-\n%s\n-\n", buf);
						}
					}
				}
			}
		}
		//TUNTAP DEVICE
		if (FD_ISSET(tun_fd, &rfds))
		{
			nread = read(tun_fd, read_buffer, sizeof(read_buffer));
			if (nread < 0)
			{
				perror("Reading from if interface");
				close(tun_fd);
				exit(EXIT_FAILURE);
			}

			printf("Read %d bytes from device %s\n", nread, tun_name);
			printAsciiHex(read_buffer, nread);

			/*
			 * ping modifier for 10.0.0.4
			 * simply swaps the last bytes of the ping packet's source and destination ips
			 * and writes it back by setting the ICMP type 0
			 */
#if 0
			printf("--------------PING MODIFIER/RESPONDER ACTIVE---------------");
			for (i = 0; i < MODIFY_LIST_LENGTH; i++)
			{
				if (!memcmp(read_buffer + 16, modify[i], 4)) //ip match
				{
					if (read_buffer[9] == 1 && read_buffer[1] == 0)
					{
						if (read_buffer[20] == 8 && read_buffer[21] == 0)
						{
							read_buffer[nread] = read_buffer[15];
							read_buffer[12] = 10; //src
							read_buffer[13] = 0; //src
							read_buffer[14] = 1; //src
							read_buffer[15] = 2; //src
							read_buffer[16] = 10; //dst
							read_buffer[17] = 0; //dst
							read_buffer[18] = 1; //dst
							read_buffer[19] = 1; //dst
//							read_buffer[20] = 0;
							write(tun_fd, read_buffer, nread);
						}
					}
				}
			}
#endif
			ax25_buffer_size = AX25_TOTAL_HEADERS_LENGTH + nread + 1; //+1 for safety
			manchester_buffer_size = (ax25_buffer_size * 2) + PREAMBLE_LENGTH + SYNC_LENGTH + 2; //+2 for EOF and NULL
			ax25_buffer = malloc(ax25_buffer_size);
			if (ax25_buffer == NULL)
			{
				perror("ax25 malloc()");
			}
			manchester_buffer = malloc(manchester_buffer_size);
			if (manchester_buffer == NULL)
			{
				perror("manchester malloc()");
			}
			//encapsulate the ip packet
			frame_length = ax25_create_ui_packet(my_ax25_callsign, ax25_destination, read_buffer, nread, ax25_buffer);
			if (frame_length == 0)
			{
				printf("couldn't prepare ax25 frame");
			}
//			printf("AX25 FRAMED\n");
//			printAsciiHex(ax25_buffer, frame_length);
			//manchester encode the ax25 frame
			frame_length = manchester_encode(ax25_buffer, manchester_buffer, frame_length);
			if (frame_length == 0)
			{
				printf("couldn't manchester encode the package");
			}
			//check for last wireless activity
			if(time(NULL) <= last_transmission_time+max_allowed_tx_interval)
			{
//				sleep(1);
				registerEvent("Discard","TX");
				printf("early transmission discard\n");
			}
			else
			{
				if(time(NULL) <= last_reception_time)
				{
					usleep(tx_message_interval);
				}
				registerEvent("TX","");
				retVal=serial_transmitCapsulatedData(manchester_buffer, frame_length);
				time(&last_transmission_time);
				if(retVal)
				{
					printf("error writing to serial port device\n");
				}
			}
			if(ax25_buffer)
			{
				free(ax25_buffer);
				ax25_buffer = NULL;
			}
			if(manchester_buffer)
			{
				free(manchester_buffer);
				manchester_buffer = NULL;
			}
			/*
			 * ping responder for 10.0.0.2
			 * simply swaps the last bytes of the ping packet's source and destination ips
			 * and writes it back by setting the ICMP type 0
			 */
#if 0		
			printf("--------------PING MODIFIER/RESPONDER ACTIVE---------------");
			for (i = 0; i < RESPOND_LIST_LENGTH; i++)
			{
				if (!memcmp(read_buffer + 16, respond[i], 4)) //ip match
				{
					if (read_buffer[9] == 1 && read_buffer[1] == 0)
					{
						if (read_buffer[20] == 8 && read_buffer[21] == 0)
						{
							read_buffer[nread] = read_buffer[15];
							read_buffer[15] = read_buffer[19];
							read_buffer[19] = read_buffer[nread];
							read_buffer[20] = 0;
							write(tun_fd, read_buffer, nread);
						}
					}
				}
			}
#endif
		}
	}
	return 0;
}
Esempio n. 2
0
int main(int argc, char *argv[]) {
	// TODO move tests somewhere better
	testIsCellVoltageRelevant();

	struct config_t *config = getConfig();
	if (!config) {
		printf("error reading configuration file\n");
		return 1;
	}
	initData(config);

	if (argc == 2) {
		if (strcmp("-c", argv[1]) == 0) {
			isCharging = TRUE;
			isDriving = FALSE;
			config->loopDelay = 20;
		}
	}

	canEventListener_init(config);

	if (buscontrol_init()) {
		return 1;
	}

	if (soc_init()) {
		return 1;
	}

	if (monitorCan_init()) {
		return 1;
	}

	if (logger_init(config)) {
		return 1;
	}

	if (serial_openSerialPort(config) != 0) {
		printf("error opening serial port\n");
		return 1;
	}

	console_init(config);
	if (isCharging) {
		if (chargercontrol_init()) {
			return 1;
		}
		chargeAlgorithm_init(config);
	}

	hiResLogger_init();

	buscontrol_setBus(TRUE);

	// send a byte to wake up the slaves
	writeWithEscape('a');

	for (unsigned char i = 0; i < data.batteryCount; i++) {
		struct battery_t *battery = data.batteries + i;
		for (unsigned short j = 0; j < battery->cellCount; j++) {
			struct status_t *cell = battery->cells + j;
			sendCommand(cell, 'r');
		}
	}

	sleep(1);

	// send some bytes to wake up the slaves (they drop characters while flashing the light)
	writeWithEscape('a');

	// findCells();

	// clear the screen
	write(1, "\E[H\E[2J", 7);

	getSlaveVersions();
	turnOffAllShunts();
	sleep(1);
	time_t whenLastOver1A = 0;
	time_t last = 0;
	for (int count = 0; TRUE; count++) {
		monitorCan_sendMonitorState(START, 0, count % 5);
		time_t t;
		time(&t);
		while (t < last + config->loopDelay) {
			monitorCan_sendMonitorState(SLEEPING, (last + config->loopDelay) - t, count % 5);
			sleep(1);
			if (!isCharging && soc_getCurrent() > 0.5) {
				// more than 0.5A discharge, must be driving
				config->loopDelay = 2;
				if (!isDriving) {
					isDriving = TRUE;
					hiResLogger_start();
				}
			}
			time(&t);
		}
		double current = soc_getCurrent();
		if (current > 0.5) {
			whenLastOver1A = t;
		}
		if (!isCharging && t - whenLastOver1A > 60) {
			config->loopDelay = 300;
			hiResLogger_stop();
			isDriving = FALSE;
		}
		last = t;
		if (config->loopDelay > 30) {
			monitorCan_sendMonitorState(WAKE_SLAVE, 0, count % 5);
			// if the slaves have gone to sleep, send some characters to wake them up
			writeWithEscape('a');
			// wait for slaves to wake up and take a measurement
			sleep(2);
		}

		// if necessary, turn off shunts and read the voltage
		shuntPause = turnOffNonKelvinResistorShunts();
		if (count % 5 == 0) {
			monitorCan_sendMonitorState(TURN_OFF_NON_KELVIN_TRANSISTOR, 0, count % 5);
			shuntPause = turnOffNonKelvinTransistorShunts() || shuntPause;
		}
		if (shuntPause) {
			// give cells time to read their real voltage
			monitorCan_sendMonitorState(WAIT_FOR_VOLTAGE_READING, 0, count % 5);
			sleep(2);
		}
		monitorCan_sendMonitorState(READ_VOLTAGE, 0, count % 5);
		getCellStates();

		// turn (back) on any shunts that are needed
		shuntPause = FALSE;
		unsigned char shuntValueChanged = FALSE;
		for (unsigned char i = 0; i < data.batteryCount; i++) {
			monitorCan_sendMonitorState(TURN_ON_SHUNTS, i, count % 5);
			shuntValueChanged |= setShuntCurrent(config, &data.batteries[i]);
		}
		// if we turned on any shunts, read the shunt current
		if (shuntValueChanged) {
			// give cells a chance re-read
			monitorCan_sendMonitorState(WAIT_FOR_SHUNT_CURRENT, 0, count % 5);
			sleep(2);
			// read the current
			monitorCan_sendMonitorState(READ_CURRENT, 0, count % 5);
			getCellStates();
		}
	}
}