距离上一篇 《半导体:Gem/Secs基本协议库的开发(1)》的分享已经过去快一年的时间了,这期间有很多朋友给我留言或者直接私信我需要SEComEnabler.SEComSimulator.exe
模拟调试软件的,本篇仍然要先说一声sorry,不过在下一篇,我举起我的小拇指发誓,一定给大家附上。
不过本文篇幅会比较长,事情定然没有那么简单。作者在一番思索之后,决定给大家一个完整的项目作为参考。本文将只会在较短的时间内免开,有需要的朋友动动你发财的小手,哈哈!
直接附上源码,上干货!!
// JcHsms.pro
QT -= gui
TEMPLATE = lib
DEFINES += JCHSMS_LIBRARY
CONFIG += c++11
CONFIG += c++11 no_debug_release
win32:CONFIG(release, debug|release){
DESTDIR = $${PWD}/../../../../deploy/lib/Release
}
else:win32:CONFIG(debug, debug|release){
DESTDIR = $${PWD}/../../../../deploy/lib/Debug
}
OBJECTS_DIR = $${PWD}/../../../../build/$${TARGET}/obj
MOC_DIR = $${PWD}/../../../../build/$${TARGET}/moc
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
JcHsms.cpp \
hsmsdatamanager.cpp \
hsmsdeviceunique.cpp \
hsmsmessage.cpp \
hsmsmessagedispatcher.cpp \
hsmsmessageheader.cpp \
secs2item.cpp
HEADERS += \
JcHsms_global.h \
JcHsms.h \
hsmsdatamanager.h \
hsmsdeviceunique.h \
hsmsincludes.h \
hsmsmessage.h \
hsmsmessagedispatcher.h \
hsmsmessageheader.h \
secs2item.h
# Default rules for deployment.
unix {
target.path = /usr/lib
}
!isEmpty(target.path): INSTALLS += target
// JcHsms_global.h
/****************************************
* JcHsms_gloab
****************************************/
#ifndef JCHSMS_GLOBAL_H
#define JCHSMS_GLOBAL_H
# define Q_DECL_EXPORT __declspec(dllexport)
# define Q_DECL_IMPORT __declspec(dllimport)
#if defined(JCHSMS_LIBRARY)
# define JCHSMS_EXPORT Q_DECL_EXPORT
#else
# define JCHSMS_EXPORT Q_DECL_IMPORT
#endif
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <mutex>
#include <stack>
/// follows depends on Qt
#include <QByteArray>
#include <QDateTime>
#include <QString>
#include <QDebug>
#include <QSet>
#include <QtEndian>
/*---------------------------------------------------------------------------*/
/* system header files */
/*---------------------------------------------------------------------------*/
#if defined(_DEBUG) && defined(WIN32) && defined(LEAK_CHECK)
#define _CRTDBG_MAP_ALLOC
#endif
#if defined(_DEBUG) && defined(WIN32) && defined(LEAK_CHECK)
#include <crtdbg.h>
#endif
#include <ctype.h>
#include <limits.h>
#ifdef _MSC_VER
#include <tchar.h>
#else
typedef char TCHAR;
#define _T(x) x
#define _stprintf sprintf
#define _stscanf scanf
#define _tcscat strcat
#define _tcschr strchr
#define _tcsstr strstr
#define _tcscmp strcmp
#define _tcscpy strcpy
#define _tcsdup strdup
#define _tcsftime strftime
#define _tcslen strlen
#define _tcsncpy strncpy
#define _tcsrchr strrchr
#define _tcstol strtol
#define _tcstoul strtoul
#define _tcstod strtod
#define _tprintf printf
#define _ttoi atoi
#define _vtprintf vprintf
#define _vstprintf vsprintf
#define _vsntprintf vsnprintf
#define _sntprintf snprintf
#endif
#ifdef __GNUC__
/* disable warning for undefined cuserid(); */
#ifndef __USE_XOPEN
#define __USE_XOPEN
#endif
#include <unistd.h>
#endif
/*****************************************************************************/
/* */
/* Symbol */
/* */
/*****************************************************************************/
/*---------------------------------------------------------------------------*/
/* Define Driver version */
/*---------------------------------------------------------------------------*/
#define JC_HSMS_DRIVER_VERSION 1.0.0.20221129_base
/*---------------------------------------------------------------------------*/
/* Define data types */
/*---------------------------------------------------------------------------*/
#if !defined(_MSC_VER) && !defined(VOID)
#define VOID void
//typedef signed char CHAR;
typedef signed long LONG;
typedef signed short SHORT;
#endif
#ifndef NULL
#define NULL 0
#endif
#ifndef UCHAR
typedef signed int INT;
typedef unsigned char UCHAR;
typedef unsigned short USHORT;
typedef unsigned int UINT;
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef void * PTR;
#endif
#ifndef ULONG
typedef unsigned long ULONG;
#endif
#ifndef BOOLEAN
typedef unsigned char BOOLEAN;
typedef short SHORTINT;
typedef long LONGINT;
typedef unsigned short SHORTCARD;
typedef unsigned long LONGCARD;
typedef LONGCARD CARDINAL;
typedef double LONGREAL;
typedef LONGINT INTEGER;
typedef float REAL;
#endif
#ifdef uchar
typedef unsigned char uchar;
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
#endif
#if _MSC_VER
typedef __int64 LONGLONG;
typedef unsigned __int64 ULONGLONG;
#elif __GNUC__
typedef long long LONGLONG;
typedef unsigned long long ULONGLONG;
#else
#error no support 64 bit data type; // LongLong ?
#endif
#ifdef BITSET
typedef unsigned long BITSET;
typedef char * ADDRESS;
typedef int (*PFI)(); /* pointer to function returning int */
typedef void (*PFV)(); /* pointer to function with no return*/
#endif
/*---------------------------------------------------------------------------*/
/* redefine global tokens */
/*---------------------------------------------------------------------------*/
#define GLOBAL
#ifndef EXTERN
#define EXTERN extern
#endif
#define PROTOTYPE extern
/*----------------------------------------------------------------------------*/
/* limit values */
/*----------------------------------------------------------------------------*/
#ifdef MSDOS
#define MAX_INT 32767
#define MAX_UINT 0xFFFF
#define MAX_INTSTR "32767"
#define MAX_UINTSTR "65535"
#else
#define MAX_INT 2147483647
#define MAX_UINT 0xFFFFFFFF
#define MAX_INTSTR "2147483647"
#define MAX_UINTSTR "4294967295"
#endif
#define MAX_SHORT 32767
#define MAX_LONG 2147483647
#define MAX_USHORT 0xFFFF
#define MAX_ULONG 0xFFFFFFFF
#define MAX_SHORTCARD 0xFFFF
#define MAX_LONGCARD 0xFFFFFFFF
#define MAX_SHORTSTR "32767"
#define MAX_LONGSTR "2147483647"
#define MAX_USHORTSTR "65535"
#define MAX_ULONGSTR "4294967295"
#define MIN_REAL ((REAL)1.40129846432481707e-45)
#define MAX_REAL ((REAL)3.40282346638528860e+38)
#define MIN_LONGREAL 4.94065645841246544e-324
#define MAX_LONGREAL 1.79769313486231470e+308
#define MAX_LLSTR "9223372036854775807"
/*****************************************************************************/
/* Define ASCII codes */
/*****************************************************************************/
#ifdef WIN32
#define DIR_SEPARATOR_STRING _TX("\\")
#define DIR_SEPARATOR_CHAR '\\'
#else
#define DIR_SEPARATOR_STRING _TX("/")
#define DIR_SEPARATOR_CHAR '/'
#endif
#define TAB '\t' /* C definition of ASCII tab */
#define NEWLINE '\n' /* C definition of ASCII newline */
#define BACKSPACE '\b' /* C definition of ASCII backspace */
#define SPACE ' ' /* white space character */
#define ESC 0x1B /* Standard definition ASCII escape */
#define BS 0x08 /* Standard definition ASCII backspace */
#define CR 0x0D /* Standard definition ASCII carriage return */
#define FF 0x0C /* Standard definition ASCII form feed */
#define BEL 0x07 /* Standard definition ASCII bell */
#define HT 0x09 /* Standard definition ASCII horizontal tab */
#define LF 0x0A /* Standard definition ASCII line feed */
#define VT 0x0B /* Standard definition ASCII virtical tab */
#define SUB 0x1A
#define RS 0x1E
/*****************************************************************************/
/* */
/* function macros */
/* */
/*****************************************************************************/
#ifndef max
#define max(a, b) ((a) >= (b) ? (a) : (b))
#endif
#ifndef min
#define min(a, b) ((a) <= (b) ? (a) : (b))
#endif
#ifndef Max
#define Max(a, b) ((a) >= (b) ? (a) : (b))
#endif
#ifndef Min
#define Min(a, b) ((a) <= (b) ? (a) : (b))
#endif
#if 0
#ifndef MAX
#define MAX(a, b) ((a) >= (b) ? (a) : (b))
#endif
#ifndef MIN
#define MIN(a, b) ((a) <= (b) ? (a) : (b))
#endif
#ifndef abs
#define abs(n) ((n) > 0 ? (n) : -(n))
#endif
#ifndef ABS
#define ABS(n) ((n) > 0 ? (n) : -(n))
#endif
#endif
/* word operation */
#define byte_high(a) (((a) >> 8) & 0x00FF)
#define byte_low(a) ((a) & 0x00FF)
#define HIGH(c) (((c) >> 8) & 0x00FF)
#define LOW(c) ((c) & 0x00FF)
#define high(c) (((c) >> 8) & 0x00FF)
#define low(c) ((c) & 0x00FF)
#define btow(h,l) (((WORD)((BYTE)(h)) << 8) | (BYTE)(l))
/* long word operation */
#define word_high(a) (((a) >> 16) & 0xFFFF)
#define word_low(a) ((a) & 0xFFFF)
/* convert byte and integer */
#ifdef _M_IX86
#define BUF_TO_SHORT(a,b) (((USHORT)(b) << 8) | ((USHORT)(a) & 0xFF))
#define SHORT_TO_BUF(w,a,b) (*((BYTE *)(b)) = ((USHORT)(w) >> 8) & 0xFF, \
*((BYTE *)(a)) = (USHORT)(w) & 0xFF)
#define BUF_TO_LONG(a,b,c,d) (((ULONG)(d) << 24) | (((ULONG)(c) << 16) & 0xFF0000) | \
(((ULONG)(b) << 8) & 0xFF00) | ((ULONG)(a) & 0xFF))
#define LONG_TO_BUF(l,a,b,c,d) (*((BYTE *)(d)) = (BYTE)((ULONG)(l) >> 24), \
*((BYTE *)(c)) = (BYTE)((ULONG)(l) >> 16), \
*((BYTE *)(b)) = (BYTE)((ULONG)(l) >> 8 ), \
*((BYTE *)(a)) = (BYTE)((ULONG)(l) & 0xFF))
#else
#define BUF_TO_SHORT(a,b) (((USHORT)(a) << 8) | ((USHORT)(b) & 0xFF))
#define SHORT_TO_BUF(w,a,b) (*((BYTE *)(a)) = (((USHORT)(w)) >> 8) & 0xFF, \
*((BYTE *)(b)) = ((USHORT)(w)) & 0xFF)
#define BUF_TO_LONG(a,b,c,d) (((ULONG)(a) << 24) | \
(((ULONG)(b) << 16) && 0xFF0000) | \
(((ULONG)(c) << 8) & 0xFF00) | ((ULONG)(d) & 0xFF))
#define LONG_TO_BUF(l,a,b,c,d) (*((BYTE *)(a)) = (BYTE)((ULONG)(l) >> 24), \
*((BYTE *)(b)) = (BYTE)((ULONG)(l) >> 16), \
*((BYTE *)(c)) = (BYTE)((ULONG)(l) >> 8), \
*((BYTE *)(d)) = (BYTE)((ULONG)(l) & 0xFF))
#endif
#define BUFPTR_TO_SHORT(p) BUF_TO_SHORT(*((BYTE *)p), *(((BYTE *)p)+1))
#define SHORT_TO_BUFPTR(l, p) SHORT_TO_BUF((l), ((BYTE *)p), (((BYTE *)p)+1))
#define BUFPTR_TO_LONG(p) BUF_TO_LONG(*(((BYTE *)p)+0), *(((BYTE *)p)+1), \
*(((BYTE *)p)+2), *(((BYTE *)p)+3))
#define LONG_TO_BUFPTR(l, p) LONG_TO_BUF((l), ((BYTE *)p), (((BYTE *)p)+1), \
(((BYTE *)p)+2), (((BYTE *)p)+3))
#define BCD_TO_BYTE(x) (((((x) >> 4) & 0xF) * 10) + ((x) & 0xF))
#define BCD_TO_SHORT(x) (((((x) >> 12) & 0xF) * 1000) + \
((((x) >> 8) & 0xF) * 100) + \
((((x) >> 4) & 0xF) * 10) + ((x) & 0xF))
#define BYTE_TO_BCD(x) (((((x) % 100) / 10) << 4) + ((x) % 10))
#define SHORT_TO_BCD(x) ((((x) / 1000) << 12) + \
((((x) % 1000) / 100) << 8) + \
((((x) % 100) / 10) << 4) + ((x) % 10))
/* check even and odd */
#define is_odd(x) ((x) & 1)
#define is_even(x) (!((x) & 1))
#define ODD(x) (((x) & 01))
#define bound_word(p) ((((p) + 1) / 2) * 2)
#define bound_long(p) ((((p) + 1) / 4) * 4)
#define EQUALSTR(s, c) ((*s == *c) && (strcmp(s, c) == 0))
/*---------------------------------------------------------------------------*/
/* define boolean */
/*---------------------------------------------------------------------------*/
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef SUCCESS
#define SUCCESS 0
#endif
#ifndef OK
#define OK 0
#endif
#ifndef NG
#define NG 1
#endif
#ifndef YES
#define YES 1
#endif
#ifndef NO
#define NO 0
#endif
#ifndef ON
#define ON 1
#endif
#ifndef OFF
#define OFF 0
#endif
#ifndef FAILURE
#define FAILURE (-1)
#endif
#define BEE_SUCCESS 0
#define BEE_ERROR (-1)
#ifndef LOOP
#define LOOP for(;;)
#endif
#ifndef BIG_ENDIAN
#define BIG_ENDIAN 1234
#define LITTLE_ENDIAN 4321
#endif
#if defined(WIN32) || defined(WIN64)
# define ENDIAN LITTLE_ENDIAN
#else
# if defined(_M_IX86) || defined(__386__) || defined(i386)
# define ENDIAN LITTLE_ENDIAN
# else
# define ENDIAN BIG_ENDIAN
# endif
#endif
#define NOT_ACHIEVE false
enum ItemFormatCode {
UNKNOWN = -1, /// unknown
LIST = 0, /// LIST (length in elements)
Binary = 8, /// Binary
Boolean = 9, /// Boolean
ASCII = 16, /// ASCII : Non-printing characters are equipment-specific
JIS8 = 17, /// JIS-8
MC = 18, /// Multi-byte charactor : UNICODE
I8 = 24, /// 8-byte integer (signed)
I1 = 25, /// 1-byte integer (signed)
I2 = 26, /// 2-byte integer (signed)
I4 = 28, /// 4-byte integer (signed)
F8 = 32, /// 8-byte floating poing
F4 = 36, /// 4-byte floating poing
U8 = 40, /// 8-byte integer (unsigned)
U1 = 41, /// 1-byte integer (unsigned)
U2 = 42, /// 2-byte integer (unsigned)
U4 = 44, /// 4-byte integer (unsigned)
STRUCT = 070,
ARRAY = 0100,
VECTOR = 0170
};
enum SelectStatus{
ConnectEstablished = 0,
AlreadyActive = 1,
NotReady = 2,
ConnectExhaust = 3
};
enum DeselectStatus{
CommunicationEnded = 0,
CommunicationNotEstablished = 1,
CommunicationBusy = 2
};
enum ReasonCode{
STypeNotSupported = 1,
PTypeNotSupported = 2,
TransactionNotOpen = 3,
EntityNotSelected = 4
};
enum WBit{ NeedReply = 1, NoReply = 0 };
enum MessageType{
ErrorMessageType = -1,
DataMessage = 0,
SelectReq = 1,
SelectRsp = 2,
DeselectReq = 3,
DeselectRsp = 4,
LinktestReq = 5,
LinktestRsp = 6,
RejectReq = 7,
SeparateReq = 9
};
#endif // JCHSMS_GLOBAL_H
// JcHsms.h
/****************************************
* JcHsms
****************************************/
#ifndef JCHSMS_H
#define JCHSMS_H
#pragma execution_character_set("utf-8")
#include "JcHsms_global.h"
#include "hsmsdeviceunique.h"
#define HSMS_LENGTHBYTE_LEN (4)
#define HSMS_MESSAGEHEADER_LEN (0xa)
#define HSMS_MESSAGE_MIN_LEN (HSMS_LENGTHBYTE_LEN + HSMS_MESSAGEHEADER_LEN)
class HsmsMessageHeader;
class HsmsMessageDispatcher;
class Secs2Item;
class HsmsMessage;
struct HsmsDeviceUnique;
class HsmsDataManager;
class JCHSMS_EXPORT JcHsms : public HsmsDeviceUnique
{
public:
JcHsms(uint16_t sessionID,QString mdln,QString softrev);
HsmsMessage interpretMessage(const QByteArray& source);
HsmsMessage originateMessage(const HsmsMessageHeader& header,const Secs2Item& item);
};
#endif // JCHSMS_H
// JcHsms.cpp
#include "JcHsms.h"
#include "hsmsdatamanager.h"
#include "hsmsdeviceunique.h"
#include "hsmsmessageheader.h"
#include "secs2item.h"
#include "hsmsmessage.h"
#define JCHSMS_DLL_VERSION "1.0.0.20221027_base"
JcHsms::JcHsms(uint16_t sessionID, QString mdln, QString softrev)
:HsmsDeviceUnique(sessionID,mdln,softrev)
{
}
HsmsMessage JcHsms::interpretMessage(const QByteArray &source)
{
return HsmsMessage(source);
}
HsmsMessage JcHsms::originateMessage(const HsmsMessageHeader& header,
const Secs2Item& item)
{
HsmsMessage hm;
hm.AddLength(HSMS_MESSAGEHEADER_LEN + item.toByteArray().length() );
hm.AddHeader(header);
hm.AddItem(item);
hm.toByteArray();
return hm;
}
// hsmsdatamanager.h
/****************************************
* HsmsDataManager
****************************************/
#ifndef HSMSDATAMANAGER_H
#define HSMSDATAMANAGER_H
#include "JcHsms_global.h"
class JCHSMS_EXPORT HsmsDataManager
{
public:
typedef struct EquipmentStatusData
{
EquipmentStatusData(){}
EquipmentStatusData( ItemFormatCode fmt,QVariant val)
: _fmt(fmt),_val(val){}
ItemFormatCode _fmt;
QVariant _val;
}ESD;
typedef QMap<uint32_t,ESD> QSsdMap;
static HsmsDataManager &Instance();
QSsdMap GetSsdMap();
void UpdateSsdMap(const uint32_t& svid,const ESD& esd);
void AddItem2SsdMap(const uint32_t& svid,const ESD& initesd);
void RemoveItemFromSsdMap(const uint32_t& svid);
private:
HsmsDataManager();
void InitSsdMap();
private:
QSsdMap SSDMap;
};
#endif // HSMSDATAMANAGER_H
// hsmsdatamanager.cpp
#include "hsmsdatamanager.h"
/****************************************
* HsmsDataManager
****************************************/
HsmsDataManager &HsmsDataManager::Instance()
{
static HsmsDataManager hsmsDtMgr;
return hsmsDtMgr;
}
HsmsDataManager::QSsdMap HsmsDataManager::GetSsdMap()
{
return SSDMap;
}
void HsmsDataManager::UpdateSsdMap(const uint32_t &svid, const HsmsDataManager::ESD &esd)
{
std::mutex _mutex;
_mutex.lock();
this->SSDMap.remove(svid);
this->SSDMap[svid] = esd;
_mutex.unlock();
}
void HsmsDataManager::AddItem2SsdMap(const uint32_t &svid, const HsmsDataManager::ESD &initesd)
{
if(SSDMap.find(svid) != SSDMap.end()){
UpdateSsdMap(svid,initesd);
}else{
SSDMap.insert(svid,initesd);
}
}
void HsmsDataManager::RemoveItemFromSsdMap(const uint32_t &svid)
{
if(SSDMap.find(svid) != SSDMap.end()){
SSDMap.remove(svid);
}
}
void HsmsDataManager::InitSsdMap()
{
/// SSD
/// 1001 I4 设备状态:0=ready 1=homing 2=warning 3=runing
/// 1002 Boolean 正压气源1报警
/// 1003 Boolean 正压气源2报警
/// 1004 Boolean 负压气源报警
/// 1005 I4 loadport 状态 0=ready 1=homing 2=warning 3=runing
/// 1006 I4 robot 状态
/// 1007 I4 aligner 状态
/// 1008 I4 code scanner 状态
/// 1009 I4 axis-X 状态
/// 1010 I4 axis-Y 状态
/// 1011 I4 axis-Z 状态
/// 1012 I4 axis-T 状态
/// 1013 I4 测距仪 状态
/// 1014 I4 主检相机 状态
/// 1015 I4 review相机 状态
/// 1016 I4 FFU状态
/// 1017 I4 离子泵状态
/// 1018 I4 左侧门1状态
/// 1019 I4 左侧门2状态
/// 1020 I4 右侧门1状态
/// 1021 I4 右侧门2状态
/// 1022 F4 机台温度 4-byte float
/// 1023 F4 机台湿度 4-byte float
SSDMap.insert(1001,ESD (I4,QVariant(0)));
for(int svid = 1002; svid <= 1004; ++svid)
SSDMap.insert(svid,ESD(Boolean,QVariant(false)));
for(int svid = 1005; svid <= 1021; ++svid)
SSDMap.insert(svid,ESD (I4,QVariant(0)));
for(int svid = 1022; svid <= 1023;++svid)
SSDMap.insert(svid,ESD(F4,QVariant(1.01)));
}
HsmsDataManager::HsmsDataManager()
{
InitSsdMap();
}
// hsmsdeviceunique.h
/****************************************
* HsmsDeviceUnique
****************************************/
#ifndef HSMSDEVICEUNIQUE_H
#define HSMSDEVICEUNIQUE_H
#include "JcHsms_global.h"
struct JCHSMS_EXPORT HsmsDeviceUnique
{
HsmsDeviceUnique(uint16_t sessionID,QString mdln,QString softrev);
static uint16_t unique_sessionID; // Equipment id or device id, be unique.
static QString unique_MDLN; // Equipment Model Type, 20bytes max
static QString unique_SOFTREV; // Software revision code, 20bytes max
};
#endif // HSMSDEVICEUNIQUE_H
// hsmsdeviceunique.cpp
/****************************************
* HsmsDeviceUnique
****************************************/
#include "hsmsdeviceunique.h"
uint16_t HsmsDeviceUnique::unique_sessionID;
QString HsmsDeviceUnique::unique_MDLN;
QString HsmsDeviceUnique::unique_SOFTREV;
HsmsDeviceUnique::HsmsDeviceUnique(uint16_t sessionID, QString mdln, QString softrev)
{
unique_sessionID = sessionID;
unique_MDLN = mdln.left(20);
unique_SOFTREV = softrev.left(20);
}
// hsmsincludes.h
#ifndef HSMSINCLUDES_H
#define HSMSINCLUDES_H
#include "JcHsms_global.h"
#include "JcHsms.h"
#include "hsmsdatamanager.h"
#include "hsmsdeviceunique.h"
#include "hsmsmessage.h"
#include "hsmsmessagedispatcher.h"
#include "hsmsmessageheader.h"
#include "secs2item.h"
#endif // HSMSINCLUDES_H
// hsmsmessage.h
/****************************************
* HsmsMessage
****************************************/
#ifndef HSMSMESSAGE_H
#define HSMSMESSAGE_H
#include "JcHsms_global.h"
#include "hsmsmessageheader.h"
#include "secs2item.h"
class JCHSMS_EXPORT HsmsMessage
{
public:
HsmsMessage(){ }
HsmsMessage(const QByteArray& source);
HsmsMessage(char* message,int len);
HsmsMessage(const HsmsMessage& primary);
const HsmsMessage & operator=(const HsmsMessage &rhs);
QString SmlString() const;
void copy(const HsmsMessage& m);
uint32_t GetLength(const QByteArray& source);
void AddLength(uint32_t n);
HsmsMessageHeader GetHeader();
void AddHeader(HsmsMessageHeader header);
void AddHeader(uint16_t sessionID,uint8_t stream,uint8_t function,
uint8_t stype,uint8_t ptype,uint32_t systembytes);
Secs2Item GetItem() const;
void AddItem(Secs2Item item);
QByteArray toByteArray();
HsmsMessage dispatch();
private:
QString SmlInterpret(
const Secs2Item &item,
QString &smlString,
QString &spaceStringfmt) const;
private:
uint32_t m_bytesLen;
HsmsMessageHeader m_header;
Secs2Item m_items;
QByteArray m_message;
};
#endif // HSMSMESSAGE_H
// hsmsmessage.cpp
#include "hsmsmessage.h"
#include "hsmsmessageheader.h"
#include "secs2item.h"
#include "hsmsmessagedispatcher.h"
/****************************************
* HsmsMessage
****************************************/
HsmsMessage::HsmsMessage(const QByteArray &source){
// assert(source.length() >= HSMS_MESSAGE_MIN_LEN);
if(source.isEmpty() || source.length() < HSMS_MESSAGE_MIN_LEN) return;
m_message = source;
m_bytesLen = GetLength(source);
m_header = HsmsMessageHeader(source.mid(HSMS_LENGTHBYTE_LEN,HSMS_MESSAGEHEADER_LEN));
m_items = Secs2Item(source.mid(HSMS_MESSAGE_MIN_LEN,source.length() - HSMS_MESSAGE_MIN_LEN));
}
HsmsMessage::HsmsMessage(char *message, int len){
QByteArray source(message,len);
m_message = source;
m_bytesLen = GetLength(source);
m_header = HsmsMessageHeader(source.mid(HSMS_LENGTHBYTE_LEN,HSMS_MESSAGEHEADER_LEN));
m_items = Secs2Item(source.mid(HSMS_MESSAGE_MIN_LEN,source.length() - HSMS_MESSAGE_MIN_LEN));
}
HsmsMessage::HsmsMessage(const HsmsMessage &primary)
{
this->copy(primary);
}
const HsmsMessage & HsmsMessage::operator=(const HsmsMessage &rhs)
{
if(this == &rhs)
return *this;
this->copy(rhs);
return *this;
}
QString HsmsMessage::SmlString() const
{
QString smlString;
QString spaceStringfmt = " ";
if(this->GetItem().isEmpty()) {
return smlString;
}
SmlInterpret(this->GetItem(),smlString,spaceStringfmt);
smlString[smlString.length() -1] = '.';
return smlString;
}
void HsmsMessage::copy(const HsmsMessage &m)
{
this->m_bytesLen = m.m_bytesLen;
this->m_header = m.m_header;
this->m_items = m.m_items;
this->m_message = m.m_message;
}
uint32_t HsmsMessage::GetLength(const QByteArray &source){
uint32_t lenA[4] = {0};
uint32_t len = 0;
lenA[0] = static_cast<uint32_t>(source.at(0));
lenA[1] = static_cast<uint32_t>(source.at(1));
lenA[2] = static_cast<uint32_t>(source.at(2));
lenA[3] = static_cast<uint32_t>(source.at(3));
#if ENDIAN == LITTLE_ENDIAN
for(int i = 0; i < 4;i++) len += (lenA[i] << ((3-i)*8 ));
#else
for(int i = 0; i < 4;i++) len += (lenA[i] << (i*8 ));
#endif
return len;
}
void HsmsMessage::AddLength(uint32_t n)
{
m_bytesLen = n;
}
HsmsMessageHeader HsmsMessage::GetHeader()
{
return m_header;
}
void HsmsMessage::AddHeader(HsmsMessageHeader header)
{
m_header = header;
}
void HsmsMessage::AddHeader(uint16_t sessionID, uint8_t stream, uint8_t function,
uint8_t stype, uint8_t ptype, uint32_t systembytes)
{
m_header = HsmsMessageHeader(sessionID,stream,function,stype,ptype,systembytes);
}
Secs2Item HsmsMessage::GetItem() const
{
return m_items;
}
void HsmsMessage::AddItem(Secs2Item item)
{
m_items = item;
}
QByteArray HsmsMessage::toByteArray()
{
if(!m_message.isEmpty())
return m_message;
m_message.clear();
// apped len bytes
m_message.append( static_cast<char>( (m_bytesLen >> 24) & 0xff)); //[0]
m_message.append( static_cast<char>( (m_bytesLen >> 16) & 0xff)); //[1]
m_message.append( static_cast<char>( (m_bytesLen >> 8) & 0xff) ); //[2]
m_message.append( static_cast<char>( (m_bytesLen >> 0) & 0xff) ); //[3]
// append message header bytes
QByteArray headerByteArray = m_header.toByteArray();
m_message.append(headerByteArray);
// append secsItems bytes
QByteArray secsItemsByteArray = m_items.toByteArray();
m_message.append(secsItemsByteArray);
return m_message;
}
HsmsMessage HsmsMessage::dispatch()
{
HsmsMessageDispatcher dispatcher;
return dispatcher.deal(*this);
}
QString HsmsMessage::SmlInterpret(
const Secs2Item &item,
QString &smlString,
QString &spaceStringfmt) const
{
/**
<L,2
<A,16 'JC Gem/Secs Test'>
<A,5 '1.0.1'>
>.
*/
if(!item.isList()) {
int fmt = item.format();
QString fmtString;
QString value;
smlString += spaceStringfmt;
switch (ItemFormatCode(fmt) )
{
case LIST : fmtString = "L" ; break;
case I1 :{
fmtString = "I1";
value.append(QChar(item.toInt8().first()));
break;
}
case I2 :{
fmtString = "I2";
value = QString::number(item.toInt16().first());
break;
}
case I4 :{
fmtString = "I4";
value = QString::number(item.toInt32().first());
break;
}
case I8 : {
fmtString = "I8";
value = QString::number(item.toInt64().first());
break;
}
case JIS8 : {
fmtString = "J";
value = QString(item.toJIS8());
break;
}
case ASCII : {
fmtString = "A";
value = item.toASCII();
break;
}
case F4 : {
fmtString = "F4";
value = QString::number( item.toFloat().first());
break;
}
case F8 :{
fmtString = "F8";
value = QString::number( item.toDouble().first());
break;
}
case U4 :{
fmtString = "U4";
value = QString::number( item.toUInt32().first());
break;
}
case U2 : {
fmtString = "U2";
value = QString::number( item.toUInt16().first());
break;
}
case U1 : {
fmtString = "U1";
value.append(QChar(item.toUInt8().first()));
break;
}
case U8 : {
fmtString = "U8";
value = QString::number(item.toUInt64().first());
break;
}
case Binary : {
fmtString = "B";
value = QString(item.toBinary());
break;
}
case MC : {
fmtString = "MC";
break;
}
case Boolean : {
fmtString = "BOOLEAN";
value = QString::number(item.toBoolean().first());
break;
}
default:
break;
}
smlString += QString("<%1,%2 '%3'>\n").arg(fmtString,QString::number(item.bytes()),value);
return smlString;
}else{
QVector<Secs2Item> v = item.GetItems();
smlString += QString("<L,%1 \n").arg(QString::number(item.bytes()));
spaceStringfmt += " ";
for(int i =0; i < v.count();++i){
SmlInterpret(v[i],smlString,spaceStringfmt);
}
smlString += ">\n";
}
return smlString;
}
// hsmsmessagedispatcher.h
/****************************************
* HsmsMessageDispatcher
****************************************/
#ifndef HSMSMESSAGEDISPATCHER_H
#define HSMSMESSAGEDISPATCHER_H
#include "JcHsms_global.h"
#include "hsmsmessage.h"
class JCHSMS_EXPORT HsmsMessageDispatcher
{
public:
HsmsMessageDispatcher();
void registerDataMessage(uint8_t stream, uint8_t function);
void unRegisterDataMessage(uint8_t stream, uint8_t function);
HsmsMessage deal( HsmsMessage primary);
HsmsMessage dealDataMsg( HsmsMessage primary);
public:
// active request
static HsmsMessage linktestReq();
static HsmsMessage selectReq(uint16_t sessionID);
static HsmsMessage S1F3(uint16_t sessionID);
private:
// response for request
HsmsMessage selectRsp(uint16_t sessionID, uint32_t systemBytes, SelectStatus status);
HsmsMessage linktestRsp(uint32_t systemBytes);
HsmsMessage S9F1(HsmsMessage primary, uint16_t sessionID);
HsmsMessage S9F3(HsmsMessage primary, uint16_t sessionID);
HsmsMessage S9F5(HsmsMessage primary, uint16_t sessionID);
HsmsMessage S1F2(HsmsMessage primary, uint16_t sessionID);
HsmsMessage S1F4(HsmsMessage primary, uint16_t sessionID);
HsmsMessage S1F14(HsmsMessage primary,uint16_t sessionID,UCHAR type);
private:
QSet<uint8_t> m_streamSet;
QSet<uint8_t> m_functionSet;
QSet<uint16_t> m_sfSet;
};
#endif // HSMSMESSAGEDISPATCHER_H
// hsmsmessagedispatcher.cpp
/****************************************
* HsmsMessageDispatcher
****************************************/
#include "hsmsmessagedispatcher.h"
#include "hsmsdatamanager.h"
HsmsMessage HsmsMessageDispatcher::selectRsp(uint16_t sessionID, uint32_t systemBytes, SelectStatus status)
{
HsmsMessage message;
message.AddLength(10);
sessionID = 0xFFFF;
HsmsMessageHeader header(sessionID/*sessionID*/,0,status,0,2,systemBytes);
message.AddHeader(header);
message.toByteArray();
return message;
}
HsmsMessage HsmsMessageDispatcher::linktestRsp(uint32_t systemBytes)
{
HsmsMessage message;
HsmsMessageHeader header(0xFFFF,0,0,0,6,systemBytes);
message.AddLength(10);
message.AddHeader(header);
return message;
}
HsmsMessage HsmsMessageDispatcher::S9F1(HsmsMessage primary, uint16_t sessionID)
{
Secs2Item it;
QByteArray a(static_cast<int>(0), static_cast<char>(0));
it.AddBinary(a);
uint32_t sb = primary.GetHeader().GetSystemBytes();
HsmsMessage hm;
hm.AddLength(10 + it.toByteArray().length() );
hm.AddHeader(sessionID,9,1,0,0,sb);
hm.AddItem(it);
return hm;
}
HsmsMessage HsmsMessageDispatcher::S9F3(HsmsMessage primary, uint16_t sessionID)
{
Secs2Item it;
QByteArray a(static_cast<int>(0), static_cast<char>(0));
it.AddBinary(a);
uint32_t sb = primary.GetHeader().GetSystemBytes();
HsmsMessage hm;
hm.AddLength(10 + it.toByteArray().length() );
hm.AddHeader(sessionID,9,3,0,0,sb);
hm.AddItem(it);
return hm;
}
HsmsMessage HsmsMessageDispatcher::S9F5(HsmsMessage primary, uint16_t sessionID)
{
Secs2Item it;
QByteArray a(static_cast<int>(0), static_cast<char>(0));
it.AddBinary(a);
uint32_t sb = primary.GetHeader().GetSystemBytes();
HsmsMessage hm;
hm.AddLength(10 + it.toByteArray().length() );
hm.AddHeader(sessionID,9,5,0,0,sb);
hm.AddItem(it);
return hm;
}
HsmsMessage HsmsMessageDispatcher::S1F2(HsmsMessage primary, uint16_t sessionID)
{
Secs2Item its[2];
its[0].AddASCII(HsmsDeviceUnique::unique_MDLN.toLatin1().constData());
its[1].AddASCII(HsmsDeviceUnique::unique_SOFTREV.toLatin1().constData());
Secs2Item it;
it.AddItems(its, 2);
uint32_t sb = primary.GetHeader().GetSystemBytes();
HsmsMessage hm;
hm.AddLength(10 + it.toByteArray().length() );
hm.AddHeader(sessionID,1,2,0,0,sb);
hm.AddItem(it);
hm.toByteArray();
return hm;
}
bool appendItem_ssd(const HsmsDataManager::EquipmentStatusData& esd,
QVector<Secs2Item>& rspItems)
{
Secs2Item item;
switch (esd._fmt) {
case Boolean: item.AddBoolean(esd._val.toBool()); break;
case ASCII: item.AddASCII(esd._val.toString()); break;
case JIS8: item.AddJIS8(esd._val.toString().toStdString().c_str()); break;
case MC : return NOT_ACHIEVE; break;
case I1 : item.AddInt8(esd._val.toChar().toLatin1()); break;
case I2: item.AddInt16((short)esd._val.toInt()); break;
case I4: item.AddInt32(esd._val.toInt()); break;
case I8: item.AddInt64(esd._val.toLongLong()); break;
case U2: item.AddUInt16((uint16_t)esd._val.toUInt()); break;
case U4: item.AddUInt32((uint32_t)esd._val.toUInt()); break;
case U8: item.AddUInt64((uint64_t)esd._val.toULongLong()); break;
case F4: item.AddFloat(esd._val.toFloat()); break;
case F8: item.AddDouble(esd._val.toDouble()); break;
default: return NOT_ACHIEVE; break;
}
rspItems.append(item);
return true;
}
HsmsMessage HsmsMessageDispatcher::S1F4(HsmsMessage primary, uint16_t sessionID)
{
// Get all svids ,and Get the value
Secs2Item item = primary.GetItem();
QVector<Secs2Item> items = item.GetItems();
QVector<Secs2Item> rspItems;
const QMap<uint32_t, HsmsDataManager::EquipmentStatusData>& m = HsmsDataManager::Instance().GetSsdMap();
for(int i = 0; i < items.size();i++){
Secs2Item item = items[i];
switch ((ItemFormatCode)item.format() )
{
case LIST : NOT_ACHIEVE; break;
case I1 : foreach (auto val, item.toInt8()) if(m.keys().contains(val)) appendItem_ssd(m[val],rspItems); break;
case I2 : foreach (auto val, item.toInt16()) if(m.keys().contains(val)) appendItem_ssd(m[val],rspItems); break;
case I4 : foreach (auto val, item.toInt32()) if(m.keys().contains(val)) appendItem_ssd(m[val],rspItems); break;
case I8 : foreach (auto val, item.toInt64()) if(m.keys().contains(val)) appendItem_ssd(m[val],rspItems); break;
case JIS8 : foreach (auto val, item.toJIS8()) if(m.keys().contains(val)) appendItem_ssd(m[val],rspItems); break;
case ASCII : NOT_ACHIEVE; break;
case F4 : foreach (auto val, item.toFloat()) if(m.keys().contains(val)) appendItem_ssd(m[val],rspItems); break;
case F8 : foreach (auto val, item.toDouble()) if(m.keys().contains(val)) appendItem_ssd(m[val],rspItems); break;
case U4 : foreach (auto val, item.toUInt32()) if(m.keys().contains(val)) appendItem_ssd(m[val],rspItems); break;
case U2 : foreach (auto val, item.toUInt16()) if(m.keys().contains(val)) appendItem_ssd(m[val],rspItems); break;
case U1 : foreach (auto val, item.toUInt8()) if(m.keys().contains(val)) appendItem_ssd(m[val],rspItems); break;
case U8 : foreach (auto val, item.toUInt64()) if(m.keys().contains(val)) appendItem_ssd(m[val],rspItems); break;
case Binary : foreach (auto val, item.toBinary()) if(m.keys().contains(val)) appendItem_ssd(m[val],rspItems); break;
case MC : NOT_ACHIEVE; break;
case Boolean: NOT_ACHIEVE; break;;
default:
break;
}
}
Secs2Item it;
it.AddItems(rspItems);
uint32_t sb = primary.GetHeader().GetSystemBytes();
HsmsMessage hm;
hm.AddLength(10 + it.toByteArray().length() );
hm.AddHeader(sessionID,1,4,0,0,sb); // S1F4
hm.AddItem(it);
hm.toByteArray();
return hm;
}
HsmsMessage HsmsMessageDispatcher::S1F14(HsmsMessage primary, uint16_t sessionID, UCHAR type)
{
//<L[2]
// 1. <B COMMACK> 0: Accepted;1: Denied, try again
// 2. <L[2] blongs to S1F13
// 1.<A MDLN>
// 2.<A SOFTREV>
uint32_t sb = primary.GetHeader().GetSystemBytes();
Secs2Item s1f13 = primary.GetItem();
Secs2Item tmp;
uint8_t x[1] = {type};
tmp.AddUInt8(x,1);
Secs2Item it ;
it = it.mergeSECS2Item(tmp,s1f13);
HsmsMessage hm;
hm.AddLength(10 + it.toByteArray().length() );
hm.AddHeader(sessionID,1,14,0,0,sb);
hm.AddItem(it);
hm.toByteArray();
return hm;
}
HsmsMessage HsmsMessageDispatcher::linktestReq()
{
HsmsMessage message;
HsmsMessageHeader header;
header.SetSessionID(0xFFFF);
header.SetStreamFunction(0, 0);
header.SetPSType(0, 5);
uint32_t sb = header.uniqueSystemBytes();
header.SetSystemBytes(sb);
message.AddLength(10); // header only
message.AddHeader(header);
return message;
}
HsmsMessage HsmsMessageDispatcher::selectReq(uint16_t sessionID)
{
HsmsMessage message;
HsmsMessageHeader header;
header.SetSessionID(sessionID);
header.SetStreamFunction(0, 0);
header.SetPSType(0, 1);
uint32_t sb = header.uniqueSystemBytes();
header.SetSystemBytes(sb);
message.AddLength(10);
message.AddHeader(header); // header only
return message;
}
HsmsMessage HsmsMessageDispatcher::S1F3(uint16_t sessionID)
{
HsmsMessage message;
HsmsMessageHeader header;
header.SetSessionID(sessionID);
header.SetStreamFunction(1, 3);
header.SetPSType(0, 0);
uint32_t sb = header.uniqueSystemBytes();
header.SetSystemBytes(sb);
QVector<Secs2Item> rspItems;
for(int i =1001; i<= 1023;i++){
Secs2Item item;
item.AddUInt32(i);
rspItems.append(item);
}
Secs2Item it;
it.AddItems(rspItems);
message.AddLength(10);
message.AddHeader(header); // header only
message.AddItem(it);
message.toByteArray();
return message;
}
HsmsMessage HsmsMessageDispatcher::dealDataMsg(HsmsMessage primary)
{
HsmsMessage mess;
HsmsMessageHeader header = primary.GetHeader();
uint16_t id = header.GetSessionID();
if(id != HsmsDeviceUnique::unique_sessionID) {
mess = S9F1(primary, HsmsDeviceUnique::unique_sessionID);
return mess;
}
uint8_t stream = header.Getstream();
uint8_t function = header.Getfunction();
uint16_t sf = stream;
sf = (sf << 8) + function;
if(!m_sfSet.contains(sf)){
if(!m_streamSet.contains(stream)){
mess = S9F3(primary, id);// unkonwn Stream
}
if(!m_functionSet.contains(function)){
mess = S9F5(primary, id); //unkonw function
}
return mess;
}
// uint32_t sb = header.GetSystemBytes();
// qDebug() << "I HsmsDevice recieve S" <<stream<<"F" <<function << " systemBytesID:"<< sb;
if(stream == 1 && function == 1)
{ // Are You There
mess = S1F2(primary,id);
}
else if(stream == 1 && function == 2)
{
qt_noop();
}
else if(stream == 1 && function == 3)
{ // SVID
mess = S1F4(primary,id);
}
else if(stream == 1 && function == 4)
{
qt_noop();
}else if(stream == 1 && function == 13)
{
mess = S1F14(primary,id,0);
}else{
qt_noop();
}
return mess;
}
HsmsMessageDispatcher::HsmsMessageDispatcher()
{
registerDataMessage(0, 0); // select
registerDataMessage(1, 1); // Are you there
registerDataMessage(1, 2);
registerDataMessage(1, 3);
registerDataMessage(1, 4);
registerDataMessage(1, 5);
registerDataMessage(1, 6);
registerDataMessage(1, 7);
registerDataMessage(1, 8);
registerDataMessage(1, 9);
registerDataMessage(1, 10);
registerDataMessage(1, 11);
registerDataMessage(1, 12);
registerDataMessage(1, 13);
registerDataMessage(1, 14);
registerDataMessage(2, 1);
registerDataMessage(2, 2);
registerDataMessage(2, 3);
registerDataMessage(2, 17); // DateTimeRequest
registerDataMessage(2, 18); // DateTimeRequest
registerDataMessage(2, 41); // NG
registerDataMessage(2, 103);// OK
registerDataMessage(6, 4);
registerDataMessage(6, 12);
registerDataMessage(6, 17);
registerDataMessage(9, 1); // Unrecognized device ID
registerDataMessage(9, 3); // Unrecognized stream type
registerDataMessage(9, 5); // Unrecognized function type
}
void HsmsMessageDispatcher::registerDataMessage(uint8_t stream, uint8_t function)
{
uint16_t x = stream;
x = (x << 8) + function;
m_sfSet.insert(x);
m_streamSet.insert(stream);
m_functionSet.insert(function);
}
void HsmsMessageDispatcher::unRegisterDataMessage(uint8_t stream, uint8_t function)
{
uint16_t x = stream;
x = (x << 8) + function;
m_sfSet.remove(x);
bool hasStream = false;
bool hasFunction = false;
foreach (const uint16_t &value, m_sfSet)
{
uint8_t s = value >> 8;
uint8_t f = value & 0xff;
if(s == stream){
hasStream = true;
}
if(f == function){
hasFunction = true;
}
}
if(!hasStream) m_streamSet.remove(stream);
if(!hasFunction) m_functionSet.remove(function);
}
HsmsMessage HsmsMessageDispatcher::deal(HsmsMessage primary)
{
HsmsMessageHeader head = primary.GetHeader();
uint16_t id = head.GetSessionID();
uint32_t sb = head.GetSystemBytes();
MessageType mt = head.GetMessageType();
HsmsMessage secondary;
switch (mt) {
case SelectReq:
secondary = selectRsp(id,sb,ConnectEstablished);
break;
case RejectReq: break;
case SelectRsp: break;
case DeselectReq: break;
case DeselectRsp: break;
case SeparateReq: break;
case LinktestReq: secondary = linktestRsp(sb); break;
case DataMessage: secondary = dealDataMsg(primary); break;
default:
break;
}
return secondary;
}
楼太高了,也避免大家视觉疲劳,接下篇~~