六. SECS/GEM封装库RapidSecs开发手记-扩展库开发-1

上一章结尾时我提到了在以上DEMO的基础上继续完善下去就可以实现GEM的全部功能,那么本章的扩展库就是真正的去实现GEM功能,不过并不是全部,而是GEM200部分,因为GEM300部分更加复杂涉及的内容太多,以后有机会再考虑这部分内容的实现。此外,扩展库的开发采用了C#,而不是基础库的C++。下面让我们开始吧……

1. 功能设计

GEM 标准定义了从用户所能看到的设备功能,以及实现这些功能所需要用到的哪些 SECS-II 消息。每个通用设备功能都是按标准规定的顺序收/发组SECS-II 消息来实现的。

扩展库的功能主要是针对SEMI标准的E30,所以要实现的功能主要有以下三个方面:

1.1 状态模型实现

状态模型就是第三章基础知识部分提到的通信状态模型、控制状态模型和设备加工状态模型,具体详见该章节。

GEM层必须维护设备的三个状态机,分别是通信状态、控制状态和加工状态。通信状态用于指示设备与主机之前的通信情况,在HSMS层进入selected状态之后,连接发起方必须发送S1F13消息,然后等接收到回复的S1F14消息则表示设备与主机之间正式建立了通信关系。控制状态和加工状态是同具体设备相关的两个状态,控制状态表示设备当前能够被主机所控制的等级,加工状态则用于描述设备当前行为。

1.2 设备功能实现

设备功能就是满足E30中规定的各项功能响应,具体支持的功能命令详见第二章中的最后部分的命令列表。

实现列表中的相关命令后将满足绝大多数对GEM200标准的需求。而对于GEM300标准的需求可以进一步在此扩展库的基础上进行。

功能命令一般分为2种:

  • 应答式命令,主机发送请求,设备回复,如S1F13、S1F3等;
  • 上报式命令,主机设置后,设备主动上报,如S5F1、S6F1、S6F11等;

2. 基础库扩展

2.1 数据接收接口扩展

增加回调函数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消息给对方。

2.2 数据发送接口扩展

增加接口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 messagefunction为偶数)。

socket send调用失败。

3. 命名空间

3.1 RapidSecs

此命名空间的内容主要是对基础库的封装,所有涉及到与基础库进行对接、交互的内容都在此进行,包括接口的封装、数据结构、类的定义等等。

3.1.1 SecsCLibWrapper

此类是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,
	}

3.1.2 HsmsSession类

从类名称应该就可以看出来,此类是用来处理HSMS(E37)会话的,比如设备模式、各类超时时间、IP地址、端口号、连接测试等,同时设置了相应的的回调函数,并在开启服务时根据设备模式进入监听状态或连接状态,停止服务时则关闭相应状态。

3.2 RapidFSM

该名字空间中定义了类”FSMBase”,是所有状态机的基类,用于各个状态之间的切换以及相关事件的发送。

GEM 给设备定义了三个状态机,分别是通信状态图、控制状态模型和加工状态图。除通信状态外,其他两个状态都跟设备具体情况相关。用户只能调用函数读取 GEM 状态,不能修改这些状态,所有状态由 GEM 自动维护。

3.2.1 通信状态

通信状态用于向操作员显示设备的当前通信状况,实现的通信状态如下:

  • Disable 状态:表示当前设备同主机之间不存在通信,该状态可能是由于系统故障引起。
  • Communicating 状态:表示设备同主机之间的通信已经建立,可以收发消息。
  • Wait_CR_from_host 状态:表示该连接由主机发起,设备正在等待主机发送 S1F13 消息。
  • Wait_delay 状态:表示该连接由设备发起,在正式建立通信的过程中出现故障,正在等待 T5 计时器终止。
  • Wait_CRA 状态:表示该连接由设备发起,已经发出 S1F13 消息,正在等待主机回复。

3.2.2 控制状态

控制状态表示主机与设备之间操作的等级,在不同控制状态下主机能对设备进行的操作不同,实现的控制状态如下:

  • Equipment_Offline 状态:在该状态下设备不响应主机的消息,等待操作员指令。
  • Attempt_Online 状态:设备响应操作员指令尝试上线,并向主机发送 S1F1消息。
  • Host_Offline 状态:设备等待主机同意设备上线,在该状态下将回复主机任何要求设备上线的消息(S1F17)。
  • Local 状态:在该状态下设备只执行操作员的直接指令,不执行主机发送的有关加工的指令。
  • Remote 状态:设备支持主机远程控制,主机可以通过通信接口操作设备进行加工。

3.2.3 加工状态

加工状态用于描述设备当前行为,实现的状态如下:

  •  INIT 状态:表示设备初始化完成。
  •  Idle 状态:表示设备等待操作指令。
  •  Pause 状态:加工程序被挂起,设备正在等待指令。
  •  Setup 状态:表示加工所需所有外部条件已经完成。
  •  Ready 状态:表示设备已经完成准备,等待操作员或主机发送的命令开始加工。
  •  Executing 状态:表示设备正在进行加工。

注意:加工状态是和具体设备的加工过程相关的,而扩展库并不是实际的设备,因此加工状态需要由用户派生具体设备时自行实现。

你可能感兴趣的:(SECS/GEM实战,c++,c#)