⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xbee_gpio_client.c

📁 Dynamic C 程式語言源碼 嵌入式控制系統 Xbee蜂群網路~
💻 C
📖 第 1 页 / 共 4 页
字号:
} gpio_signal[GPIO_MAX_SIGNALS];

enum {                // GPIO states
	CLIENT_STATE_IDLE = 0,      // Client state idle must be zero
	CLIENT_STATE_REQ_INFO,
   CLIENT_STATE_PARSE_INFO,
   CLIENT_STATE_NEW_NAME,
	CLIENT_STATE_REQ_NAME,
   CLIENT_STATE_PARSE_NAME,
	CLIENT_STATE_REQ_ANARANGE,
   CLIENT_STATE_PARSE_ANARANGE,
   CLIENT_STATE_REQ_READ,
	CLIENT_STATE_PARSE_READ,
   CLIENT_STATE_PARSE_WRITE
};

enum {              // Main function states
	ZB_IDLE,
	ZB_NODE_OPEN,
   ZB_EXIT
};

enum {              // Command parsing states
	PARSE_CMD,       // Parse command component
	PARSE_SIGNAL,    // Parse signal ID component
	PARSE_VALUE,     // Parse value component
	PARSE_DONE,      // Parse complete, execute command and exit
	PARSE_ERROR,     // Error, print message and exit (keep below PARSE_DONE)
	PARSE_EXIT       // Exit parsing function         (keep below PARSE_DONE)
};

enum {              // Signal commands
   SIGNAL_GET,      // Get value(s) from one or all signal sources
   SIGNAL_SET       // Set value to output signal
};

#define SHOW_NET_HELP   1
#define SHOW_GPIO_HELP  2
#define SHOW_SIGNALS    4

// function prototypes for sending packet requests to a gpio node
void find_gpio_servers(void);
int query_gpio_node(void);
int request_gpio_info(int node_index);
int request_gpio_names(int node_index, int io_start, int io_end);
int request_gpio_ana_range(int node_index, int io_start, int io_end);
int request_gpio_read(int node_index, int io_start, int io_end);
void gpio_help(int flags);

int request_gpio(int node_index, int cluster, char *data, int len)
{
	int err;

	_zb_NodeData_t				*nodeData;
	zb_sendAddress_t			sendAddr;

	nodeData = GET_NODE_DATA(node_index);

	if (nodeData == NULL) {

#ifdef GPIO_VERBOSE
		printf("request_gpio: invalid node_index (%d)\n", node_index);
#endif
		return -1;
	}

	zb_MakeEndpointClusterAddr(node_index, XBEE_ENDPOINT_RESPONSE,
		XBEE_ENDPOINT_GPIO, cluster, &sendAddr);

	sendAddr.msg = data;
	sendAddr.msglen = len;

#ifdef GPIO_VERBOSE
	printf("sending cluster 0x%02x to node %d:\n", cluster, node_index);
	xb_hexdump(data, len);
#endif

	err = zb_send(&sendAddr);
	if (err) {
#ifdef GPIO_VERBOSE
		printf("request_gpio: error %d sending\n", err);
#endif
		return err;
	}

#ifdef GPIO_VERBOSE
   printf("request_gpio: sent 0x%02x request\n", cluster);
#endif
   gpio_device[gpio_index].last_request = (byte) cluster;
   gpio_device[gpio_index].request_sent = MS_TIMER;
   return 0;
}

void find_gpio_servers(void)
{
	int node_index, i;
	_zb_NodeData_t *nodeData;
   int err;

   printf("\nScanning network nodes for GPIO servers.\n\n");
	memset(&gpio_device, 0, sizeof(gpio_device));
   for (i = 0; i < GPIO_MAX_SERVERS; gpio_device[i++].node_index = -1);

	node_index = gpio_index = 0;
	while( nodeData=GET_NODE_DATA(node_index) )
	{
#ifdef GPIO_VERBOSE
		printf("%d A:%04X P:%04X %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X",
			node_index,	ntohs(nodeData->nwk_addr), ntohs(nodeData->parent_NetAddr),
			nodeData->who[0],nodeData->who[1],
			nodeData->who[2],nodeData->who[3],nodeData->who[4],
			nodeData->who[5],nodeData->who[6],nodeData->who[7]);
      printf(" %s [%s]\n", (nodeData->active) ? "  Active" : "Inactive",
      	nodeData->remoteID);
#endif
      // Query possible gpio device
	   gpio_device[gpio_index].state = CLIENT_STATE_REQ_INFO;
      gpio_device[gpio_index].node_index = node_index;
      while (!query_gpio_node()) {
         zb_tick();
      }
      // See if response was received from gpio info request
      if (gpio_device[gpio_index].io_count) {
         printf("  %d: Type = %04x, I/O Count = %d\n", gpio_index,
                   gpio_device[gpio_index].device_type,
                   gpio_device[gpio_index].io_count);
         // Increase the server count
         gpio_index++;
         if (gpio_index >= GPIO_MAX_SERVERS) {
            // If maximum reached, stop scanning
            return;
         }
      }
      // Move to next node on network
		++node_index;
	}
}


int query_gpio_node(void)
{
   int i, end, min, max;
   gpio_device_t *gpio;
   unsigned long check;

   gpio = &gpio_device[gpio_index];

	switch (gpio->state) {
		case CLIENT_STATE_IDLE:
         gpio->ep_count = 0;
			break;                   // When idle, node discovery complete

		case CLIENT_STATE_REQ_INFO:
         // Send GPIO info request to see if node is a GPIO server
         //  If error received, set state to idle to move on
         gpio->state = (request_gpio_info(gpio->node_index) ?
                       CLIENT_STATE_IDLE : CLIENT_STATE_PARSE_INFO);
			break;

      case CLIENT_STATE_PARSE_INFO:
         // Wait for I/O count from server
         if (gpio->io_count) {
            gpio->state = CLIENT_STATE_IDLE;
         }
         break;

      case CLIENT_STATE_NEW_NAME:
         // Clear any existing signal information and drop into request
       	memset(&gpio_signal, 0, sizeof(gpio_signal));
		case CLIENT_STATE_REQ_NAME:
         // Query server for names and info for all available signals
         min = (gpio->ep_count ? gpio->io_count - gpio->ep_count : 0);
			if (!request_gpio_names(gpio->node_index, min, gpio->io_count - 1))
         {
            gpio->state = CLIENT_STATE_PARSE_NAME;
            gpio->ep_count = gpio->io_count - min;
         }
			break;

      case CLIENT_STATE_REQ_ANARANGE:
         // Find group of analog signal inputs
         if (gpio->ep_count) {
            min = gpio->last_ep - gpio->ep_count + 1;
         }
         else {
	         for (i = max = 0, min = -1, end = gpio->io_count;
	                  i < end; i++)
	         {
	            if (gpio_signal[i].type == XBEE_GPIO_TYPE_ANALOG_IN) {
	               if (min < 0) min = i;
	               max = i;
	            }
	         }
         }
         // If analog inputs exist, query for range settings
         if (min >= 0 && !request_gpio_ana_range(gpio->node_index, min, max)) {
            gpio->state = CLIENT_STATE_PARSE_ANARANGE;
            gpio->ep_count = max - min + 1;
         }
         else {
	         gpio->state = CLIENT_STATE_IDLE;
            gpio_help(SHOW_GPIO_HELP);
         }
         break;

      case CLIENT_STATE_REQ_READ:
         request_gpio_read(gpio->node_index, gpio->last_ep - gpio->ep_count + 1,
                            gpio->last_ep);
         break;

      case CLIENT_STATE_PARSE_NAME:
      case CLIENT_STATE_PARSE_ANARANGE:
      case CLIENT_STATE_PARSE_READ:
      case CLIENT_STATE_PARSE_WRITE:
         // Wait for end point count to drop to zero, then node is back to idle
         if (gpio->ep_count == 0) {
            if (gpio->state == CLIENT_STATE_PARSE_ANARANGE) {
               gpio_help(SHOW_GPIO_HELP);
		         gpio->state = CLIENT_STATE_IDLE;
            }
            else {
               if (gpio->state == CLIENT_STATE_PARSE_NAME) {
                  gpio->state = CLIENT_STATE_IDLE;
                  gpio_help(SHOW_SIGNALS | SHOW_GPIO_HELP);
                  return 1;   // Printing help may cause timeout so return here
               }
               else {
                  printf("\nG> ");
			         gpio->state = CLIENT_STATE_IDLE;
               }
            }
         }
         break;

      default:
         gpio->state = CLIENT_STATE_IDLE;
         break;
	}

   if (gpio->state != CLIENT_STATE_IDLE) {
	   // Check for timeout of response/operation
      check = MS_TIMER;
	   if (check - gpio->request_sent > GPIO_TIMEOUT) {
#ifdef GPIO_VERBOSE
	      printf("\nResponse has timed out. (%d:%d:%d)\n\n", gpio_index,
	          gpio->node_index , gpio->state);
#endif
	      gpio->state = CLIENT_STATE_IDLE;
	   }
      else {
         return 0;
      }
   }
   return 1;
}

int request_gpio_info(int node_index)
{
	int err;

	// send a single null byte, msg points to an empty string (null byte)
	err = request_gpio(node_index, XBEE_GPIO_CLUST_INFO, "", 1);
	if (! err) {
	   gpio_device[gpio_index].node_index = node_index;
      gpio_device[gpio_index].io_count = 0;
	}

   return err;
}

void xbeeGpioDevInfoResp(char *frame, int framelen)
{
	xbee_frame_gpio_info_t	*gpio_info;

	gpio_info = (xbee_frame_gpio_info_t *) frame;

	if (framelen < sizeof(*gpio_info)) {
#ifdef GPIO_VERBOSE
		printf("dev info response too short (%d bytes)\n", framelen);
#endif
		return;
	}

#ifdef GPIO_VERBOSE
	printf("Received device info response:\n");
	printf("  Cluster Ver: %d   I/O Count: %u\n",
		gpio_info->protocol_ver, gpio_info->io_count);
	printf("  Manufacturer: 0x%04x   Device: 0x%04x   Firmware: %u.%02u\n",
		gpio_info->manufacturer, gpio_info->device_type,
		gpio_info->firmware_ver >> 8, gpio_info->firmware_ver & 0x00FF);
#endif
	gpio_device[gpio_index].io_count = gpio_info->io_count;
	gpio_device[gpio_index].device_type = gpio_info->device_type;
}

int request_gpio_iorange(int node_index, int cluster, int io_start, int io_end)
{
	int i, req_count;
	char request[XBEE_MAX_RFPAYLOAD];

	req_count = 0;
	for (i = io_start; (i <= io_end) && (req_count < XBEE_RFPAYLOAD_SIZE); i++) {
		request[req_count++] = i;
	}

	return request_gpio(node_index, cluster, request, req_count);
}

int request_gpio_names(int node_index, int io_start, int io_end)
{
	return request_gpio_iorange(node_index, XBEE_GPIO_CLUST_NAME, io_start,
		io_end);
}

void xbeeGpioNameResp(char *data, int datalen)
{
   int index;
	xbee_gpio_rec_name_resp_t	*resp;

#ifdef GPIO_VERBOSE
	printf("parsing name response\n");
	xb_hexdump(data, datalen);
#endif

	while (datalen >= 2) {
		resp = (xbee_gpio_rec_name_resp_t *) data;
		if (resp->type == 0xFF) {
#ifdef GPIO_VERBOSE
			printf("  io%3d: invalid\n");
#endif
			datalen -= 2;
			data += 2;
		} else {
			if (datalen < 3) {
#ifdef GPIO_VERBOSE
	         printf("  incomplete packet, %d extra byte(s) at end\n", datalen);
#endif
	         datalen = 0;
            break;
			}
			if (resp->namelen + 3 > datalen) {
#ifdef GPIO_VERBOSE
				printf("  io%3d: decode error, namelen (%d) too long for packet\n",
					resp->signal, resp->namelen);
#endif
			}
			if (resp->namelen > 20) {
#ifdef GPIO_VERBOSE
				printf("  io%3d: decode error, namelen (%d) invalid\n",
					resp->signal, resp->namelen);
#endif
			}

         memcpy(gpio_signal[resp->signal].name, resp->name, resp->namelen);
         gpio_signal[resp->signal].name[resp->namelen] = '\0';
         gpio_signal[resp->signal].index = resp->signal;
         gpio_signal[resp->signal].type = resp->type;
         if (gpio_device[gpio_index].ep_count) {
            gpio_device[gpio_index].ep_count--;
         }
#ifdef GPIO_VERBOSE
         printf("  io%3d: type 0x%02x, name=%s\n", resp->signal, resp->type,
            gpio_signal[resp->signal].name);
#endif
         datalen -= resp->namelen + 3;
         data += resp->namelen + 3;
		}
	}

#ifdef GPIO_VERBOSE
   if (datalen)
   {
      printf("  bad packet, 1 extra byte at end (0x%02x)\n", *data);
   }
#endif
   if (gpio_device[gpio_index].ep_count) {
      gpio_device[gpio_index].state = CLIENT_STATE_REQ_NAME;
   }
}

int request_gpio_ana_range(int node_index, int io_start, int io_end)
{
	return request_gpio_iorange(node_index, XBEE_GPIO_CLUST_ANA_RANGE, io_start,
		io_end);
}

void xbeeGpioAnaRangeResp(char *data, int datalen)
{
	int units_len, record_len;
	char units[16];

	xbee_gpio_rec_ar_resp_units_t *resp;
	xbee_gpio_rec_ar_resp_range_t *range;

#ifdef GPIO_VERBOSE
	printf("parsing analog range response\n");
	xb_hexdump(data, datalen);
#endif

	while (datalen >= 2) {
		resp = (xbee_gpio_rec_ar_resp_units_t *) data;
		if (resp->length == 0xFF) {
#ifdef GPIO_VERBOSE
			printf("  %s(%3d): invalid/not analog I/O\n",
                   gpio_signal[resp->signal].name, resp->signal);
#endif
			datalen -= 2;
			data += 2;
		} else {
			units_len = resp->length & 0x0F;
			record_len = 2 + units_len;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -