安装Visual Studio 2017及以上版本并选择用于构建C程序(而不仅仅是C++)的选项。
将zForceSDK-x.x.x.zip提取到任何文件夹
该示例程序包含在 SDK 中的原因有两个,一是允许您开始与触摸传感器模块进行通信,二是作为创建自己的应用程序的起点。
①打开解决方案文件 zForceSDK-Example.sln,执行以下任一操作:
a. 打开Visual Studio 2017 。
b. 从文件资源管理器打开它。
②确保配置设置为“x64”。
③选择构建类型:Release或Debug
④在菜单中选择生成(build) ? 构建解决方案( Build Solution)。
结果:创建了 zForceSDK 目录。
①将手势条通过USB与PC机进行连接
②从文件资源管理器中,打开文件夹 zForceSDK\Windows\x86-64。
③复制 zForce.dll。
④打开文件夹 zForceSDK\x64 将 zForce.dll 粘贴到子文件夹 Release 或子文件夹 Debug 中(根据所选配置,两者都会出现)
⑤ 选择“调试(Debug )”?“开始调试(Start Debugging)”,或“调试”(Debug )?“开始调试(不执行)(Start without Debugging)”
运行结果如下:
运行结果分析如下:
根据运行结果分析如下:
1. 首先,创建了一个连接并成功连接到设备。
2. 发现了2个设备,其中一个设备名称为"Air"。
3. 接收到了一个消息,消息序列号为1,消息类型为OperationModesMessageType,表示接收到了操作模式消息。
- 操作模式报告显示检测模式打开,信号模式关闭,LED亮度模式关闭,检测HID模式关闭。
4. 接收到了一个消息,消息序列号为2,消息类型为McuUniqueIdentifierMessageType,表示接收到了微控制器唯一标识符消息。
- 打印了微控制器唯一标识符为450055000751363334393737。
5. 接收到了一个消息,消息序列号为3,消息类型为EnableMessageType,表示接收到了启用消息。
- 启用状态为是,连续模式为是,消息数量为0。
根据运行结果,可以看出代码成功连接到设备,接收到了不同类型的消息,并根据消息类型进行相应的处理。
/*! \file
这段代码是一个示例程序,展示了如何使用zForce SDK。它连接到一个设备,初始化zForce库,并执行一系列操作。
1、代码创建了一个Connection对象,并使用hidpipe协议连接到设备。这个Connection对象用于与设备进行通信。
2、代码通过Connection对象找到了Platform设备和Sensor设备。Platform设备通常表示与传感器相关的平台信息,而Sensor设备则表示实际的传感器设备。
代码之后设置了Sensor设备的操作模式,并进入一个无限循环。
3、在循环中,代码等待来自设备的消息,并根据消息的类型做出相应的处理。
当收到EnableMessageType类型的消息时,表示已成功启用设备并可以接收通知。
当收到OperationModesMessageType类型的消息时,表示成功获取了MCU唯一标识符。
当收到McuUniqueIdentifierMessageType类型的消息时,表示已成功设置了传感器设备的使能状态。
4、最后,代码在Destroy函数中关闭了所有资源,并在SignalHandler函数中处理了程序终止的信号。
*/
// 这里包含一些C标准库头文件以及一些zForce SDK的头文件。
// Header Files
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif // _WIN32
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#include <signal.h>
#include <zForceCommon.h>
#include <OsAbstractionLayer.h>
#include <zForce.h>
#include <Queue.h>
#include <Connection.h>
#include <Device.h>
#include <Message.h>
#include "ErrorString.h"
#include "DumpMessage.h"
// 这里定义了一些宏常量,用于表示设备的厂商ID、产品ID以及测试分辨率。
#define HIDDEVICEVID "0x1536" // Vendor ID of Device.
#define HIDDEVICEPID "0x0101" // Product ID of Device.
#define TESTRESOLUTIONX1 640
#define TESTRESOLUTIONY1 480
#define TESTRESOLUTIONZ1 100
// 这些是函数的前向声明,用于后面的函数实现或调用。
void DumpMessage (Message * message);
void DumpEnableMessage (Message * message);
void DumpDisableMessage (Message * message);
void DumpOperationModesMessage (Message * message);
void DumpResolutionMessage (Message * message);
void DumpTouchActiveArea (Message * message);
void DumpReverseTouchActiveArea (Message * message);
void DumpTouchMessage (Message * message);
void DumpNumberOfTrackedObjectsMessage (Message * message);
void DumpFingerFrequencyMessage (Message * message);
void DumpIdleFrequencyMessage (Message * message);
void DumpDetectedObjectSizeRestrictionMessage (Message * message);
void DumpMessageError (Message * message);
char * ErrorString (int errorCode);
void DoDisable (SensorDevice * sensorDevice);
void DoEnable (SensorDevice * sensorDevice);
void DoOperationModes (SensorDevice * sensorDevice);
void DoTouchActiveArea (SensorDevice * sensorDevice);
void DoResolution (SensorDevice * sensorDevice);
void DoNumberOfTrackedObjects (SensorDevice * sensorDevice);
void DoFingerFrequency (SensorDevice * sensorDevice);
void DoIdleFrequency (SensorDevice * sensorDevice);
void DoDetectedObjectSizeRestrictionMessage (SensorDevice * sensorDevice);
/*
* We will let the user quit the program by pressing
* Control-C. In such an event SignalHandler will be called.
*/
void SignalHandler (int sig);
/*
* The procedure we sue to close everything down correctly.
*/
void Destroy (void);
// Local (static) Variables
// 定义了一些静态变量和函数的声明。
static bool zForceInitialized = false;
static Connection * MyConnection = NULL;
static bool IsConnected = false;
int main (void)
{
// 首先调用了zForce_Initialize函数进行zForce库的初始化,并检查初始化的结果。如果初始化失败,打印错误信息并退出程序。
bool resultCode = zForce_Initialize (NULL);
if (resultCode)
{
zForceInitialized = true;
}
else
{
printf ("zForce initialization failed.\n");
Destroy ();
exit (-1);
}
// Install the Control-C handler.
// 这里设置了信号处理函数,当收到SIGINT信号(通常是用户按下Ctrl+C)时,会调用SignalHandler函数。
signal (SIGINT, SignalHandler);
// Here we connect to a device using hidpipe.
//
// HidPipeTransport (hidpipe) has the following options:
//
// vid: Vendor ID. Current neonode sensors have VID 0x1536.
// pid: Product ID. Current neonode sensors have PID 0x0101.
// index: If the computer has multiple connected Neonode sensors,
// the first one has index 0, the second has index 1, etc.
// Note: The order is decided by the Operating System.
//
// Asn1Protocol (asn1) currently has no options.
//
// StreamingDataFrame (Streaming) is the DataFrame type used by both
// HidPipeTransport and Asn1Protocol.
// 创建了一个Connection对象,并使用hidpipe协议连接到设备。hidpipe协议需要指定设备的厂商ID、产品ID和索引。
MyConnection = Connection_New (
"hidpipe://vid="HIDDEVICEVID",pid="HIDDEVICEPID",index=0", // Transport
"asn1://", // Protocol
"Streaming"); // DataFrame type. Both Transport and Protocol must support the same.
// 检查Connection对象的创建是否成功,如果失败则打印错误信息并退出程序。
// 然后尝试连接到设备,如果连接失败则打印错误信息并退出程序。
if (NULL == MyConnection)
{
printf ("Unable to create connection: (%d) %s.\n",
zForceErrno,
ErrorString (zForceErrno));
Destroy ();
exit (-1);
}
printf ("Connection created.\n");
printf ("Connecting to Device.\n");
bool connectionAttemptResult = MyConnection->Connect (MyConnection);
if (!connectionAttemptResult)
{
printf ("Unable to connect to device: (%d) %s\n",
zForceErrno,
ErrorString (zForceErrno));
Destroy ();
exit (-1);
}
// Wait for Connection response to arrive within 1000 seconds.
// 这里从Connection对象的连接队列中获取连接消息(ConnectionMessage)。如果获取失败,则打印错误信息并退出程序。
ConnectionMessage * connectionMessage =
MyConnection->ConnectionQueue->Dequeue (MyConnection->ConnectionQueue,
1000000);
if (NULL == connectionMessage)
{
printf ("No Connection Message Received.\n");
printf (" Reason: %s\n", ErrorString (zForceErrno));
Destroy ();
exit (-1);
}
printf ("Devices: %d\n", MyConnection->NumberOfDevices);
// 通过Connection对象的FindDevice函数找到了Platform设备和Sensor设备。如果没有找到对应的设备,则打印错误信息并退出程序。
PlatformDevice * platformDevice =
(PlatformDevice *)MyConnection->FindDevice (MyConnection, Platform, 0);
if (NULL == platformDevice)
{
printf ("No Platform device found.\n");
Destroy ();
exit (-1);
}
// Find the first Sensor type device (Core/Air/Plus).
SensorDevice * sensorDevice =
(SensorDevice *)MyConnection->FindDevice (MyConnection, Sensor, 0);
if (NULL == sensorDevice)
{
printf ("No Sensor device found.\n");
Destroy ();
exit (-1);
}
char * deviceTypeString = NULL;
DeviceType deviceType = sensorDevice->DeviceType & ~Sensor;
switch (deviceType)
{
case Platform:
deviceTypeString = "Platform";
break;
case Core:
deviceTypeString = "Core";
break;
case Air:
deviceTypeString = "Air";
break;
case Plus:
deviceTypeString = "Plus";
break;
case Lighting:
deviceTypeString = "Lighting";
break;
default:
deviceTypeString = "Unknown";
break;
}
printf ("Found Device: %s.\n", deviceTypeString);
/*
* The sequence will now be
* 1) SetOperationModes.
* 2) GetResolution.
* 3) GetMcuUniqueIdentifier.
* 4) Enable notifications.
*
*/
// 设置了Sensor设备的操作模式
if (!sensorDevice->SetOperationModes (sensorDevice,
DetectionMode|SignalsMode|LedLevelsMode|DetectionHidMode|GesturesMode,
DetectionMode))
{
printf ("SetOperationModes error (%d) %s.\n", zForceErrno, ErrorString (zForceErrno));
Destroy ();
exit (-1);
}
for (;;)
{
// Wait for the answer to arrive, timeout after 1 second (1000ms).
#define DEQUEUETIMEOUT 1000
// 从设备队列中获取消息。通过调用Dequeue函数,传入设备队列和超时时间来获取消息。
Message * message = MyConnection->DeviceQueue->Dequeue (MyConnection->DeviceQueue, DEQUEUETIMEOUT);
if (NULL != message)
{
DumpMessage (message);
switch (message->MessageType)
{
case EnableMessageType:
/* We are enabled and can now receive notifications */
break;
case OperationModesMessageType:
if (!platformDevice->GetMcuUniqueIdentifier (platformDevice))
{
printf ("GetMcuUniqueIdentifier error (%d) %s.\n", zForceErrno, ErrorString(zForceErrno));
Destroy();
exit(-1);
}
break;
case McuUniqueIdentifierMessageType:
if (!sensorDevice->SetEnable (sensorDevice, true, 0))
{
printf ("SetEnable error (%d) %s.\n", zForceErrno, ErrorString (zForceErrno));
Destroy ();
exit (-1);
}
break;
default:
/* Do nothing */
break;
}
message->Destructor (message);
}
// 从连接队列中获取连接消息
connectionMessage = MyConnection->ConnectionQueue->Dequeue (MyConnection->ConnectionQueue, 0);
if (NULL != connectionMessage)
{ // 根据连接消息的ConnectionStatus进行不同的处理:
switch (connectionMessage->ConnectionStatus)
{
case Connected: // 表示已连接成功
/* Should only be received upon connect. */
printf ("Connection status: Connected\n");
/* Do nothing */
break;
case Disconnected: // 表示连接已断开,打印相应的信息,然后调用Destroy函数释放资源并退出程序
/* Should only be received if the program calls MyConnection->Disconnect(MyConnection); */
printf ("Connection status: Disconnected\n");
Destroy ();
exit (0);
break;
case ConnectionFault: // 表示连接出现故障,可能是传感器物理断开或系统不再识别传感器,打印错误信息,然后调用Destroy函数释放资源并退出程序
/* This should only happen if the sensor is physically disconnected or no longer
recognised by the system (i.e driver crash or similar). */
printf ("Connection status: (%d) %s\n", connectionMessage->ErrorCode,
ErrorString (connectionMessage->ErrorCode));
Destroy ();
exit (-1);
break;
default:
/* Do nothing */
break;
}
// 释放连接消息对象
connectionMessage->Destructor(connectionMessage);
}
}
// 释放资源
Destroy ();
}
// 用于释放资源。如果zForce库已经初始化,则调用zForce_Uninitialize函数进行释放。
void Destroy (void)
{
if (IsConnected)
{
MyConnection->Disconnect (MyConnection);
IsConnected = false;
}
if (NULL != MyConnection)
{
MyConnection->Destructor (MyConnection);
}
if (zForceInitialized)
{
zForce_Uninitialize ();
zForceInitialized = false;
}
}
void SignalHandler (int sig)
{
(void) sig;
Destroy ();
exit (-1);
}