# OCPP
[toc]
# Interface standards for electric vehicles


[嘗試在 Python 和 OSS 中與 SteVe 一起使用 OCPP(開放充電點協議)](https://yomon.hatenablog.com/entry/try_ocpp_with_steve)
# 第四、五章 Operations Initiated by Charge Point&Central System(Message)
檔案名稱==ocpp_def.h== `include OCPP16JAPP.h`
Charge Point: <span style= "background:lightblue" >XXXXXX</span>
Central System: <span style= "background:orange" >XXXXXX</span>
| | Abbreviations |request(.req)|configuration(.conf)
|:------------:|:-------------:| :-------------:| :-------------:|
| <span style= "background:lightblue">Authorize</span>| sAuth |O|O|
|<span style= "background:lightblue">Start Transaction</span>|sStartTxn|O|O|
|<span style= "background:lightblue">Stop Transaction</span>| sStopTxn |O|O|
|<span style= "background:lightblue">Status Notification</span>|sStatusNotif|O|X|
|<span style= "background:lightblue">Diagnostics Status Notification</span>|sDiagStatusNotif |O|X|
|<span style= "background:lightblue">Firmware Status Notification</span>|sFwStatusNotif|O|X|
| <span style= "background:orange" > Cancel Reservation</span> | sCancelRsrv |O|O|
| <span style= "background:orange" > Change Availability</span> | sChngAvail |O|O|
| <span style= "background:orange" > Change Configuration</span> | sChngConfig |O|O|
| <span style= "background:orange" > Clear Cache</span> | sClrCache |X|O|
| <span style= "background:orange" > Data Transfer</span> | sDataTxfer |O|O|
| <span style= "background:orange" >Get Configuration</span>| sGetConfig |O|O|
| <span style= "background:orange" >Get Diagnostics</span>| sGetDiag |O|O|
| <span style= "background:orange" >Get Local List Version| sGetLocalListVer |X|O|
| <span style= "background:orange" >Remote Start Transaction</span>| sRemoteStartTxn |O|O|
| <span style= "background:orange" >Remote Stop Transaction</span>| sRemoteStopTxn |O|O|
| <span style= "background:orange" >Reserve Now</span>| sRsrvNow |O|O|
| <span style= "background:orange" >Reset</span>| sRst |O|O|
| <span style= "background:orange" >Send Local List</span>| sSendLocalList |X|O|
| <span style= "background:orange" >Unlock Connector Transaction</span>| sUnlockConntr |O|O|
| <span style= "background:orange" >Update Firmware</span>| sUpdateFW |O|O|
:::info
<font color="#f00">紅色代表:uint8_t</font>
<font color="#0f0">綠色代表:int8_t</font>
<font color="#00f">藍色代表:uint32_t</font>
<font color="#f0f">粉色代表:int32_t</font>
<font color="#ff0">黃色代表:double</font>
:::
結構 tOCPPShM_t
>sOCPP
>><font color="#f00">InitNOK、InitMemErr、IsUp2ndFW、IsChgrLocked、CmdSend[4]</font>、<font color="#f0f">ConfStatus、OutCurrLimit</font>、
<font color="#ff0">OutPwrLimit</font>
>>##########以下為Charge Point相關##########
>>sAuth
>>>sReq:{<font color="#f00">IdTag[20]</font>}
>>>sConf:{<font color="#f00">ParentIdTag[20]、Status</font>、<font color="#f0f">ExpDate</font>}
>>sStartTxn
>>>sReq:{<font color="#f00">IdTag[20]</font>、<font color="#f0f">ConnID、Time、MeterStart、RsrvID</font>}
>>>sConf:{<font color="#f00">ParentIdTag[20]、Status</font>、<font color="#f0f">TransID、ExpDate</font>}
>>sStopTxn
>>>sReq:{<font color="#f00">IdTag[20]</font>、<font color="#f0f">TransID、Time、MeterStop</font>}
>>>sConf:{<font color="#f00">ParentIdTag[20]、Status</font>、<font color="#f0f">ExpDate</font>}
>>sStatusNotif
>>>sReq:{<font color="#f00">Status、ErrCode、Info[50]、VendorID[255]、VendorErrCode[50]</font>、<font color="#f0f">ConnID、Time</font>}
>>sDiagStatusNotif
>>>sReq:{<font color="#f00">status</font>}
>>sFwStatusNotif
>>>sReq:{<font color="#f00">Status</font>}
>>##########以下為Central System相關##########
>>sCancelRsrv
>>>sReq:{<font color="#f0f">RsrvID</font>}
>>>sConf:{<font color="#f00">Status</font>}
>>sChngAvail
>>>sReq:{<font color="#f00">Type</font>、<font color="#f0f">ConnID</font>}
>>>sConf:{<font color="#f00">Status</font>}
>>sChngConfig
>>>sReq:{<font color="#f00">Key[50]、Value[500]</font>}
>>>sConf:{<font color="#f00">Status</font>}
>>sClrCache
>>>sConf:{<font color="#f00">Status</font>}
>>sDataTxfer
>>>sReq:{<font color="#f00">VendorID[255]、MsgID[50]</font>}
>>>sConf:{<font color="#f00">Status</font>}
>>sGetConfig
>>>sReq:{<font color="#f00">Key[10][32]</font>、<font color="#f0f">SizeKey</font>}
>>>sConf:{<font color="#f00">SizeKey、SizeUnkey、KeyValue[19]:{Key[32]、RO、Value[64]}</font>}
>>sGetDiag
>>>sReq:{<font color="#f00">Location[500]、CmdUpDiag</font>、<font color="#f0f">Retries、RetryInterval、StartTime、StopTime</font>}
>>>sConf:{<font color="#f00">FileName[255]</font>}
>>sGetLocalListVer
>>>sConf:{<font color="#f0f">Version</font>}
>>sRemoteStartTxn
>>>sReq:{<font color="#f00">IdTag[20]</font>、<font color="#f0f">ConnID</font>}
>>>sConf:{<font color="#f00">Status</font>}
>>sRemoteStopTxn
>>>sReq:{<font color="#f0f">TransID</font>}
>>>sConf:{<font color="#f00">Status</font>}
>>sRsrvNow
>>>sReq:{<font color="#f00">IdTag[20]、ParentID[20]</font>、<font color="#f0f">ConnID、ExpiryDate、RsrvID</font>}
>>>sConf:{<font color="#f00">Status、Occupied</font>}
>>sRst
>>>sReq:{<font color="#f00">Type</font>}
>>>sConf:{<font color="#f00">Status</font>}
>>sSendLocalList
>>>sConf:{<font color="#f00">Status</font>}
>>sUnlockConntr
>>>sReq:{<font color="#f0f">ConnID</font>}
>>>sConf:{<font color="#f00">Status</font>}
>>sUpdateFW
>>>sReq:{<font color="#f00">Location[500]</font>、<font color="#f0f">RetrieveDate、Retries、RetryInterval</font>}
>>>sConf:{<font color="#f0f">Update</font>}
>sAuth
>><font color="#f00">InitNOK、DevNOK、FwUpNOK、InitMemErr、IsWaitTimeUp、Authed、Ok2Chg、CmdRst、CmdRemoteStart、NtfUnplug、ChgUsrID[64]、StopReason、GunSelect</font>、<font color="#00f">CardMoney、InAcWh</font>、<font color="#f0f">TransID、TransID_Up</font>
---
## 參考資料
[啟動 docker-compose 發生 ERROR](https://oranwind.org/-solution-qi-dong-docker-compose-fa-sheng-error-couldnt-connect-to-docker-daemon-at-httpdockerlocalunixsocket-is-it-running-cuo-wu/)

[SteVe 和 Charge Point](https://yomon.hatenablog.com/entry/try_ocpp_with_steve)
[最簡單完整的libwebsockets的例子](https://www.twblogs.net/a/5e6b1590bd9eee211685ec6d)
## MessageType process
```c
#include <stdio.h>
#include <string.h>
static unsigned char MessageType(unsigned char *str)
{
unsigned char *Sptr,*Eptr;
int i,len;
if((Sptr=strstr(str,"["))==NULL)
return 0;
if((Eptr=strstr(Sptr,","))==NULL)
return 0;
len=Eptr-Sptr;
printf("str: %s\nSptr: %s\nEptr: %s\nlen: %d\n",str,Sptr,Eptr,len);
printf("Sptr: 0x%x\n",*Sptr);
Sptr++;
printf("Sptr++: 0x%x\n",*Sptr);
for(i=0;i<len;i++)
{
if((*(Sptr+i)>=0x32)&&(*(Sptr+i)<=0x34))
return (*(Sptr+i)&0x0F);
}
return 0;
}
int main()
{
char pu8SendBuf[1024*10];
unsigned char MsgType=0;
sprintf(pu8SendBuf, "[2,\"%s\",{\"status\":\"%s\"}]"
, "19223201"
, "Accepted");
MsgType = MessageType(pu8SendBuf);
printf("MsgType: %d\n",MsgType);
return 0;
}
```
## UniqueID
```c
#include <stdio.h>
#include <string.h>
static int UniqueID(unsigned char *str,unsigned char *UniID)
{
unsigned char *Sptr,*Eptr;
int i,len;
if((Sptr=strstr(str,","))==NULL)
return 0;
printf("Sptr: 0x%x\n",*Sptr);//,
Sptr++;
printf("Sptr++: 0x%x\n",*Sptr);//"
if((Eptr=strstr(Sptr,","))==NULL)
return 0;
len=Eptr-Sptr;
printf("len: %d\n",len);
for(i=0;i<len;i++)
{
if(*(Sptr+i)==0x22)
{
Sptr+=i;
break;
}
}
if(i==len)
return 0;
memset(UniID,0,strlen(UniID));
Sptr++;
len-=i;
for(i=0;i<len;i++)
{
if(*(Sptr+i)==0x22)
{
*(UniID+i)=0x00;
printf("UniID+%d: %s\n", i,(UniID+i));
break;
}
*(UniID+i)=*(Sptr+i);
printf("UniID+%d: %s\n", i,(UniID+i));
}
return i;
}
int main()
{
char pu8SendBuf[1024*10];
char pu8UniqID[64];
sprintf(pu8SendBuf, "[2,\"%s\",{\"status\":\"%s\"}]"
, "19223201"
, "Accepted");
UniqueID(pu8SendBuf, pu8UniqID);
printf("pu8UniqID: %s\n", pu8UniqID);
return 0;
}
```
## GetPayloadString
```c
#include <stdio.h>
#include <string.h>
static int GetPayloadString(unsigned char *str,unsigned char *Pattern, unsigned char *Data)
{
unsigned char *Sptr,*Eptr,Flag=0;
int i,k=0;
if(strlen(str)<=0)
return 0;
if((Sptr=strstr(str,Pattern))==NULL)
return 0;
printf("Sptr: %s\n", Sptr);
Sptr+=strlen(Pattern);
for(i=0;;i++)
{
if(*(Sptr+i)==':')
break;
if(*(Sptr+i)==0x00)
return 0;
}
Sptr+=(i+1);
printf("Sptr+=(%d+1): %s\n", i, Sptr);
for(i=0;;i++)
{
if(Flag==1)
{
*(Data+k)=*(Sptr+i);
printf("Flag_%d=>(Data+%d): %c\n", Flag, k, *(Sptr+i));
k++;
}
if(*(Sptr+i)==0x22)//0x22=> "
Flag++;
if(Flag==2)
{
*(Data+(k-1))=0x00;
printf("Flag_%d: %s\n", Flag, Data);
return Sptr+i-str;
}
if(*(Sptr+i)==0x00)
return 0;
}
}
int main()
{
char pu8SendBuf[1024*10];
char pu8UniqID[64];
sprintf(pu8SendBuf, "[2,\"%s\",{\"status\":\"%s\"}]"
, "19223201"
, "Accepted");
GetPayloadString(pu8SendBuf,"status", pu8UniqID);
printf("GetPayloadString: %s\n", pu8UniqID);
return 0;
}
```
## UtcToEpoch
```c
#include <stdio.h>
#include <string.h>
#include <time.h>
static int GetPayloadString(unsigned char *str,unsigned char *Pattern, unsigned char *Data)
{
unsigned char *Sptr,*Eptr,Flag=0;
int i,k=0;
if(strlen(str)<=0)
return 0;
if((Sptr=strstr(str,Pattern))==NULL)
return 0;
printf("Sptr: %s\n", Sptr);
Sptr+=strlen(Pattern);
for(i=0;;i++)
{
if(*(Sptr+i)==':')
break;
if(*(Sptr+i)==0x00)
return 0;
}
Sptr+=(i+1);
printf("Sptr+=(%d+1): %s\n", i, Sptr);
for(i=0;;i++)
{
if(Flag==1)
{
*(Data+k)=*(Sptr+i);
printf("Flag_%d=>(Data+%d): %c\n", Flag, k, *(Sptr+i));
k++;
}
if(*(Sptr+i)==0x22)//0x22=> "
Flag++;
if(Flag==2)
{
*(Data+(k-1))=0x00;
printf("Flag_%d: %s\n", Flag, Data);
return Sptr+i-str;
}
if(*(Sptr+i)==0x00)
return 0;
}
}
void show(unsigned char *O, unsigned char *F)
{
unsigned char TmpData[8];
memset(TmpData,0,sizeof(TmpData));
printf("-----------------------\naddr: O(%p) F(%p) \n", O, F);
printf("S: %s\n", O);
printf("F: %s\n", F);
memcpy(TmpData,O,F-O);
printf("TmpData: %s\n", TmpData);
}
static unsigned int UtcToEpoch(unsigned char *UtcDataTime)
{
//YYYY-MM-DDTHH:MM:SS , return UTC+00:00
unsigned char TmpData[8],*Sptr,*Eptr;
struct tm tm;
unsigned int TimeZone=0,EpochTime=0;
memset(&tm,0,sizeof(struct tm));
//year
memset(TmpData,0,sizeof(TmpData));
if((Sptr=strstr(UtcDataTime,"-"))==NULL)
return 0;
memcpy(TmpData,UtcDataTime,Sptr-UtcDataTime);
show(UtcDataTime,Sptr);
tm.tm_year=atoi(TmpData)-1900;
Sptr++;
//month
memset(TmpData,0,sizeof(TmpData));
if((Eptr=strstr(Sptr,"-"))==NULL)
return 0;
memcpy(TmpData,Sptr,Eptr-Sptr);
show(Sptr,Eptr);
tm.tm_mon=atoi(TmpData)-1;
Eptr++;
//day
memset(TmpData,0,sizeof(TmpData));
if((Sptr=strstr(Eptr,"T"))==NULL)
return 0;
memcpy(TmpData,Eptr,Sptr-Eptr);
show(Eptr,Sptr);
tm.tm_mday=atoi(TmpData);
Sptr++;
//HH
memset(TmpData,0,sizeof(TmpData));
if((Eptr=strstr(Sptr,":"))==NULL)
return 0;
memcpy(TmpData,Sptr,Eptr-Sptr);
show(Sptr,Eptr);
tm.tm_hour=atoi(TmpData);
Eptr++;
//MM
memset(TmpData,0,sizeof(TmpData));
if((Sptr=strstr(Eptr,":"))==NULL)
return 0;
memcpy(TmpData,Eptr,Sptr-Eptr);
show(Eptr,Sptr);
tm.tm_min=atoi(TmpData);
Sptr++;
//SS
memset(TmpData,0,sizeof(TmpData));
if((Eptr=strstr(Sptr,"Z"))!=NULL)
{
memcpy(TmpData,Sptr,Eptr-Sptr);
show(Sptr,Eptr);
tm.tm_sec=atoi(TmpData);
EpochTime=(unsigned int)mktime(&tm);
}
else if((Eptr=strstr(Sptr,"+"))!=NULL)
{
memcpy(TmpData,Sptr,Eptr-Sptr);
tm.tm_sec=atoi(TmpData);
EpochTime=(unsigned int)mktime(&tm);
Eptr++;
memset(TmpData,0,sizeof(TmpData));
if((Sptr=strstr(Eptr,":"))!=NULL)
{
memcpy(TmpData,Eptr,Sptr-Eptr);
TimeZone=atoi(TmpData)*60*60;
Sptr++;
memset(TmpData,0,sizeof(TmpData));
strcpy(TmpData,Sptr);
TimeZone+=(atoi(TmpData)*60);
}
else
{
strcpy(TmpData,Eptr);
TimeZone=atoi(TmpData)*60*60;
}
EpochTime-=TimeZone;
}
else if((Eptr=strstr(Sptr,"-"))!=NULL)
{
memcpy(TmpData,Sptr,Eptr-Sptr);
tm.tm_sec=atoi(TmpData);
EpochTime=(unsigned int)mktime(&tm);
Eptr++;
memset(TmpData,0,sizeof(TmpData));
if((Sptr=strstr(Eptr,":"))!=NULL)
{
memcpy(TmpData,Eptr,Sptr-Eptr);
TimeZone=atoi(TmpData)*60*60;
Sptr++;
memset(TmpData,0,sizeof(TmpData));
strcpy(TmpData,Sptr);
TimeZone+=(atoi(TmpData)*60);
}
else
{
strcpy(TmpData,Eptr);
TimeZone=atoi(TmpData)*60*60;
}
EpochTime+=TimeZone;
}
else if((Eptr=strstr(Sptr,"."))!=NULL)
{
memcpy(TmpData,Sptr,Eptr-Sptr);
tm.tm_sec=atoi(TmpData);
EpochTime=(unsigned int)mktime(&tm);
}
else
EpochTime=(unsigned int)mktime(&tm);
return EpochTime;
}
int main()
{
char pu8SendBuf[1024*10];
char ResponseCurrentTime[64];
unsigned int EpochTime = 0;
sprintf(pu8SendBuf, "[3,\"%s\",{\"status\":\"%s\", \"currentTime\":\"%s\", \"heartbeatInterval\": 300}]"
, "19223201"
, "Accepted"
, "2013-02-01T20:53:32.486Z"
);
GetPayloadString(pu8SendBuf,"currentTime", ResponseCurrentTime);
EpochTime = UtcToEpoch(ResponseCurrentTime);
printf("-----------------------\nGetPayloadString: %s\nEpochTime: %d\n", ResponseCurrentTime,EpochTime);
return 0;
}
```