上一章结尾时我提到了在以上DEMO的基础上继续完善下去就可以实现GEM的全部功能,那么本章的扩展库就是真正的去实现GEM功能,不过并不是全部,而是GEM200部分,因为GEM300部分更加复杂涉及的内容太多,以后有机会再考虑这部分内容的实现。此外,扩展库的开发采用了C#,而不是基础库的C++。下面让我们开始吧……
GEM 标准定义了从用户所能看到的设备功能,以及实现这些功能所需要用到的哪些 SECS-II 消息。每个通用设备功能都是按标准规定的顺序收/发组SECS-II 消息来实现的。
扩展库的功能主要是针对SEMI标准的E30,所以要实现的功能主要有以下三个方面:
状态模型就是第三章基础知识部分提到的通信状态模型、控制状态模型和设备加工状态模型,具体详见该章节。
GEM层必须维护设备的三个状态机,分别是通信状态、控制状态和加工状态。通信状态用于指示设备与主机之前的通信情况,在HSMS层进入selected状态之后,连接发起方必须发送S1F13消息,然后等接收到回复的S1F14消息则表示设备与主机之间正式建立了通信关系。控制状态和加工状态是同具体设备相关的两个状态,控制状态表示设备当前能够被主机所控制的等级,加工状态则用于描述设备当前行为。
设备功能就是满足E30中规定的各项功能响应,具体支持的功能命令详见第二章中的最后部分的命令列表。
实现列表中的相关命令后将满足绝大多数对GEM200标准的需求。而对于GEM300标准的需求可以进一步在此扩展库的基础上进行。
功能命令一般分为2种:
增加回调函数rapid_secs_on_recv_raw_data
接收到消息后触发的回调,此处回调的是收到的原始数据。用户可在此进行相关处理,比如回应消息、执行操作等。
语法:
typedef DWORD(__stdcall *rapid_secs_on_recv_raw_data)( RSECSH session_h, unsigned long msg_id, unsigned char stream, unsigned char function, const char* data_ptr, unsigned int data_len ); |
参数:
session_h
[in] HSMS连接对象句柄。
msg_id
[in] 接收到的消息id。
stream
[in] 接收到的消息stream。
function
[in] 接收到的消息function。
data_ptr
[in] 接收到的数据指针。
data_len
[in] 接收到的数据长度。
返回值:
值 |
描述 |
RAPID_SECS_SUCCESS |
表示消息处理成功。 |
RAPID_SECS _ERROR_USN |
不支持此消息的stream。返回此值后,RapidSecs库将自动发送S9,F3消息给对方。 |
RAPID_SECS _ERROR_UFN |
不支持此消息的function。返回此值后,RapidSecs库将自动发送S9,F5消息给对方。 |
RAPID_SECS _ERROR_IDN |
消息数据错误。返回此值后,RapidSecs库将自动发送S9,F7消息给对方。 |
增加接口rapid_secs_send_msg_buf
消息发送接口,将在C#中进行数据的封装。
语法:
RAPID_SECS_API unsigned long rapid_secs_send_msg_buf( RSECSH session_h, unsigned char stream, unsigned char function, const char* ptr_data, int data_length, unsigned long flags, unsigned long msg_id ); |
参数:
session_h
[in] HSMS连接对象句柄。
stream
[in] 要发送的消息stream。
function
[in] 要发送的消息function。
ptr_data
[in] 消息数据指针。
flags
[in] 需要对方回复时,设为RAPID_SECS_FLAGS_NEED_REPLY;不需回复时,设为0。
msg_id
[in] 消息ID。
返回值:
值 |
描述 |
> 0 |
发送成功。返回值为已发送消息的id。 |
0 |
发送错误。可能原因: HSMS句柄无效。 Stream无效(大于127)。 发送的消息不是primary message(function为偶数)。 socket send调用失败。 |
此命名空间的内容主要是对基础库的封装,所有涉及到与基础库进行对接、交互的内容都在此进行,包括接口的封装、数据结构、类的定义等等。
此类是C++库接口封装类,代码如下:
///
/// SecsCLibWrapper主要是对C++库接口的封装
///
internal static class SecsCLibWrapper
{
const string DLL_NAME = "RapidSecs.dll";
[DllImportAttribute(DLL_NAME, EntryPoint = "rapid_create_secs", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr CreateSecs(ref SecsSets sSet);
[DllImportAttribute(DLL_NAME, EntryPoint = "rapid_destroy_secs", CallingConvention = CallingConvention.Cdecl)]
public static extern void DestroySecs(IntPtr hSecs);
[DllImportAttribute(DLL_NAME, EntryPoint = "rapid_secs_startup_server", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAsAttribute(UnmanagedType.Bool)]
public static extern bool SecsStartupServer(IntPtr hServer);
[DllImportAttribute(DLL_NAME, EntryPoint = "rapid_secs_close_server", CallingConvention = CallingConvention.Cdecl)]
public static extern void SecsCloseServer(IntPtr hServer);
[DllImportAttribute(DLL_NAME, EntryPoint = "rapid_secs_connect", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAsAttribute(UnmanagedType.Bool)]
public static extern bool SecsConnect(IntPtr hSecs, UInt32 ulIP, UInt16 usPort);
[DllImportAttribute(DLL_NAME, EntryPoint = "rapid_secs_disconnect", CallingConvention = CallingConvention.Cdecl)]
public static extern void SecsDisconnect(IntPtr hSecs);
[DllImportAttribute(DLL_NAME, EntryPoint = "rapid_secs_send_msg_buf", CallingConvention = CallingConvention.Cdecl)]
public static extern uint SecsSendMessageBuffer(IntPtr hSecs, byte stream, byte func, IntPtr dataBuffer, int dataLen, uint flag, uint msgId);
[DllImportAttribute(DLL_NAME, EntryPoint = "rapid_if_secs_connect", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAsAttribute(UnmanagedType.Bool)]
public static extern bool IfSecsconnect(IntPtr hSecs);
}
部分结构体的定义如下:
public enum COMMACK : byte
{
Accepted = 0,
Denied = 1,
}
public enum ONLACK : byte
{
Accepted = 0,
NotAllowed = 1,
OnlineAlready = 2,
}
public enum EAC : byte
{
Acknowledge = 0,
DeniedECIDNotExist = 1,
DeniedBusy = 2,
DeniedOutOfRange = 3,
}
从类名称应该就可以看出来,此类是用来处理HSMS(E37)会话的,比如设备模式、各类超时时间、IP地址、端口号、连接测试等,同时设置了相应的的回调函数,并在开启服务时根据设备模式进入监听状态或连接状态,停止服务时则关闭相应状态。
该名字空间中定义了类”FSMBase”,是所有状态机的基类,用于各个状态之间的切换以及相关事件的发送。
GEM 给设备定义了三个状态机,分别是通信状态图、控制状态模型和加工状态图。除通信状态外,其他两个状态都跟设备具体情况相关。用户只能调用函数读取 GEM 状态,不能修改这些状态,所有状态由 GEM 自动维护。
通信状态用于向操作员显示设备的当前通信状况,实现的通信状态如下:
控制状态表示主机与设备之间操作的等级,在不同控制状态下主机能对设备进行的操作不同,实现的控制状态如下:
加工状态用于描述设备当前行为,实现的状态如下:
注意:加工状态是和具体设备的加工过程相关的,而扩展库并不是实际的设备,因此加工状态需要由用户派生具体设备时自行实现。