Escolar Documentos
Profissional Documentos
Cultura Documentos
Objetivos
O objetivo do SMW Communication Kit SDK o de fornecer as ferramentas necessrias para auxiliar os desenvolvedores durante
o processo de integrao de novos acessrios de comunicao aos medidores da famlia SMW. As metas especficas deste projeto
incluem, mas no se limitam a:
Utilizar as funes de leitura e escrita de parmetros do projeto Modbus nas transaes com o medidor;
Utilizar os algoritmos de segurana (AES-256, CBC, ECDSA e SDH) do projeto Security para autenticao e criptografia;
Implementar o mecanismo de "aperto-de-mos" para o estabelecimento de sesso segura com o medidor;
Implementar a lista de atributos suportados por medidores da famlia SMW;
Realizar a escolha da funo Modbus correta de acordo com o atributo solicitado;
Verificar as respostas e retornar interface target o contedo das mensagens;
Encapsular as funcionalidades do SDK em uma nica static library.
Viso Arquitetural
O SDK uma biblioteca esttica independente de hardware que pode ser compilada para qualquer sistema que atenda a critrios
mnimos de RAM, ROM e capacidade de processamento. Ela encapsula as funcionalidades da biblioteca Modbus e de Security e
implementa as "queries" ou perguntas que podem ser realizadas para os medidores da famlia SMW. Existem quatro interfaces para
o sistema target:
Requerida
Memory.c - Realiza manipulaes em memria RAM. As principais funes so New(), Delete(), Set() e Compare().
Muitos sistemas podem utilizar o port existente, que utiliza as funes da biblioteca standard do ANSI C.
SerialPort.c - Para as funes de inicializao, leitura e escrita na porta serial. Tambm pode ser utilizada como wrapper
para outros meios (ex.: UDP/IP).
KeyLoader.c - Retorna as chaves de segurana utilizadas pelo SDK. O sistema target deve fornecer as chaves utilizadas
pelo SDK.
Fornecida
QueryManager.h - a principal interface fornecida pelo SDK que permite a abertura de sesso e comunicao com o
medidor.
01.12.2016
1/13
Abaixo um simples programa que utiliza o SDK para ler a tenso RMS do medidor e encerra logo aps:
staticvoidmyListener(uint8_tstate){
uint8_trcvBuffer[255]={0};
size_trcvLength=0;
/*CopythealreadyvalidatedresponsefromSDKbuffer.*/
Receive(rcvBuffer,sizeofrcvBuffer,&rcvLength);
/*Dumpthereceivedmessage.*/
printf("\r\nResponse(%zu):\r\n",rcvLength);
for(size_ti=0;i<rcvLength;i++)
printf("%02x",rcvBuffer[i]);
printf("\r\n");
}
intmain(intargc,char**argv){
/**
*Startasecuresessionwiththemeterandregistertheapplication
*listenertoreceiveresponsenotifications.
*/
Initialize("/dev/ttyUSB1",myListener);
/**
*RequesttheRMSvoltagetothemeter.myListener()willbeinvoked
*oncethereplyortimeoutarrives.
*/
Send(kInstantaneousRMSVoltage,NULL,0);
/*Closethesecuresession.*/
DeInitialize();
}
01.12.2016
2/13
O observador chamado sempre que uma resposta Modbus tiver sido recebida e estiver disponvel para o uso na aplicao. Esta
funcionalidade til especialmente no modo em que a resposta Modbus ocorre em uma thread independente a da requisio,
conhecido como modo non-blocking. No modo blocking a porta serial fica bloqueada at receber a resposta ou ocorrer timeout, no
sendo necessria a notificao.
Criando o port
A realizao do port do SDK para uma nova plataforma consiste na implementao das interfaces requeridas mencionadas na Viso
Arquitetural:
Memory.c
Encapsula as funes de gerenciamento de memria utilizadas no sistema target. Uma implementao tpica do Memory.c
utilizando a biblioteca padro C pode ser desta forma:
#include"Memory.h"
void*New(constvoid*type,...){
/*Obtainthesizeoftheobject.*/
constsize_tsize=*(constsize_t*)type;
/*Allocatesmemoryfortheobject.*/
void*instance=malloc(size);
/*Objectinstance.*/
returninstance;
}
voidDelete(void**instance){
/*Releaseinstance,ifexists.*/
if(*instance){
free(*instance);
*instance=NULL;
}
}
void*Copy(void*to,constvoid*from,size_tsize){
memcpy(to,from,size);
01.12.2016
3/13
returnto;
}
void*Set(void*block,int8_tvalue,size_tsize){
memset(block,value,size);
return0;
}
int32_tCompare(constvoid*str1,constvoid*str2,size_tn){
returnmemcmp(str1,str2,n);
}
SerialPort.c
Implementa as funes de leitura e escrita na porta serial. Abaixo um exemplo para a plataforma Windows em modo blocking:
#include"SerialPortWindows.h"
/*Windowsserialporthandler.*/
void*_fd=INVALID_HANDLE_VALUE;
staticSerialListener_notify;/*<Callbacktonotifyaboutincomingreplies.*/
int8_tSerialPortInit(constcharportName[],SerialListenerlistener){
/*Opentheserialport.*/
DWORDaccessDirection=GENERIC_READ|GENERIC_WRITE;
_fd=CreateFile(portName,accessDirection,0,0,OPEN_EXISTING,0,0);
if(_fd==INVALID_HANDLE_VALUE)
return-1;
/*Obtainportstate.*/
DCBdcbSerialParams={0};
dcbSerialParams.DCBlength=sizeof(dcbSerialParams);
if(!GetCommState(_fd,&dcbSerialParams))
return-1;
/*Definegeneralcommunicationparameters.*/
dcbSerialParams.BaudRate=115200;
dcbSerialParams.ByteSize=8;
dcbSerialParams.StopBits=2;
dcbSerialParams.Parity=0;
if(!SetCommState(_fd,&dcbSerialParams))
return-1;
/*Configuretime-outparameters.*/
COMMTIMEOUTStimeouts={0};
timeouts.ReadIntervalTimeout=-1;
timeouts.ReadTotalTimeoutConstant=0;
timeouts.ReadTotalTimeoutMultiplier=1000;
timeouts.WriteTotalTimeoutConstant=0;
timeouts.WriteTotalTimeoutMultiplier=0;
if(!SetCommTimeouts(_fd,&timeouts))
return-1;
/*Configuretheserialobserver.*/
01.12.2016
4/13
if(!listener)
return-1;
_notify=listener;
/*Returnsuccess.*/
return0;
}
int8_tSerialPortDeInit(void){
CloseHandle(_fd);
/*Returncode.*/
return(_fd==INVALID_HANDLE_VALUE)?
-1:0;
}
int8_tSerialPortRead(uint8_t*buffer,uint8_tlength,uint8_t*readLength){
DWORDnBytesRead=0;
uint8_ttemporaryBuffer=0;
uint8_ti=1;
/*Checkthebufferispreviouslyallocated.*/
if(buffer==NULL)
return-1;
/*Checkthenumberofbytesreadpointerispreviouslyallocated.*/
if(readLength==NULL)
return-1;
do{
if(!ReadFile(_fd,&temporaryBuffer,1,&nBytesRead,NULL))
break;
buffer[i-1]=temporaryBuffer;
i++;
}while(nBytesRead>0&&i<length);
/*Numberofbytesread.*/
*readLength=i-2;
/*Returnsuccess.*/
return0;
}
int8_tSerialPortWrite(uint8_t*buffer,uint8_tlength){
DWORDnBytesWritten=0;
/*Writequery.*/
if(!WriteFile(_fd,buffer,length,&nBytesWritten,NULL))
return-1;
_notify();
/*Returnsuccess.*/
return0;
}
int8_tSerialPortSetTimeOut(uint32_tportTimeOut){
/*Holdtime-outparameters.*/
COMMTIMEOUTStimeouts={0};
01.12.2016
5/13
/*Retrievecurrenttime-outparameters.*/
if(!GetCommTimeouts(_fd,&timeouts))
return-1;
/*Definethenewtime-outvalue.*/
timeouts.ReadTotalTimeoutMultiplier=portTimeOut;
/*Setthenewtime-out.*/
if(!SetCommTimeouts(_fd,&timeouts))
return-1;
/*Returnsuccess.*/
return0;
}
int8_tSerialPortIsBlocking(){
return1;
}
E no arquivo .h:
/**
*@fileSerialPortWindows.h
*@authorRichardH.Baeumle<richardhb@weg.net>
*@version1.0
*@briefImplementstheModbusserialporthandlerforWindowssystems.
*
*Thisfilecontainthedefinitionofthenecessaryfunctionstoinitialize,
*readandwritedataonaserialport.
*
*Copyright2015WEGAutomacaoLtda.AllRightsReserved.
*/
#ifndefSERIAL_PORT_WINDOWS_H
#defineSERIAL_PORT_WINDOWS_H
#ifdef__cplusplus
extern"C"{
#endif
/*StandardC.*/
#include<stdint.h>/*<Standardintegerdatatypes.*/
#include<stdio.h>/*<Printerroranddebugmessages.*/
#include<string.h>/*<Erroroutput.*/
/*Windows.*/
#include<windows.h>/*<DefinitionsusedbytheterminalI/Ointerfaces.*/
/*SDK.*/
#include"SerialPort.h"/*<Definitionofportinterfacestobeimplemented.*/
#ifdef__cplusplus
}
#endif
#endif/*SERIAL_PORT_WINDOWS_H*/
KeyLoader.c
01.12.2016
6/13
Permite que o SDK recupere as chaves e assinaturas necessrias durante a autenticao com o medidor. Uma implementao
bsica pode ser desta forma:
#include"KeyLoader.h"
externvoidGetPrivateKey(uint8_tbuffer[],size_tbufferLength,
size_t*keyLength){
/*System'sprivatekey.*/
constuint8_tprivateKey[]={
0x69,0xdf,0xce,0x0f,0x78,0xc6,0xbe,0xdb,
0x8f,0xbb,0x44,0xb9,0x86,0x1c,0xea,0x68,
0x55,0xbc,0xac,0xa9,0x32,0x54,0x9b,0x4d,
0x6a,0xe5,0x61,0xfc,0x64,0x2b,0x75,0x68
};
*keyLength=sizeofprivateKey;
/*CopytoSDKbuffer.*/
Copy(buffer,privateKey,(*keyLength<bufferLength)?
*keyLength:bufferLength);
}
externvoidGetPublicKey(uint8_tbuffer[],size_tbufferLength,
size_t*keyLength){
/*System'spublickey.*/
constuint8_tpublicKey[]={
0x04,0xd9,0x4f,0x0c,0x5b,0x91,0xae,0xeb,
0xf0,0xd1,0x22,0x86,0x2b,0xf0,0x49,0x32,
0x71,0xe1,0x5d,0x1e,0x13,0x53,0xf2,0x82,
0x70,0xcc,0xaa,0x7f,0x51,0xe2,0x39,0x01,
0x4a,0xc1,0xa3,0xf9,0xe0,0x5f,0x3b,0x4f,
0x1c,0x0b,0xd3,0xb8,0x09,0x6b,0xeb,0xd2,
0xc4,0xf0,0x87,0x57,0x27,0x36,0x51,0xc2,
0x01,0xcc,0x20,0x9c,0x26,0x2d,0x44,0x50,
0x66,0x00/*<lastbyteispaddingtofitwordsize.*/
};
*keyLength=sizeofpublicKey;
/*CopytoSDKbuffer.*/
Copy(buffer,publicKey,(*keyLength<bufferLength)?
*keyLength:bufferLength);
}
externvoidGetCaKey(uint8_tbuffer[],size_tbufferLength,
size_t*keyLength){
/*CA'spublickey.*/
constuint8_tcaKey[]={
0x04,0xc7,0x88,0x61,0x33,0x57,0x77,0x58,
0xac,0xcf,0x3b,0x8a,0xba,0x9d,0xc6,0x99,
0xf0,0x3f,0x68,0x8d,0x7e,0x34,0x03,0xef,
0x80,0x45,0x45,0x8e,0xe5,0xf0,0x78,0xc4,
0x37,0x47,0x8c,0xc4,0xef,0x48,0xdb,0x2f,
0xb2,0xa7,0x6d,0x83,0xf4,0x09,0x14,0x34,
0xf3,0xd5,0xfc,0xf5,0xb6,0x99,0x28,0xac,
0x31,0xc6,0x22,0x44,0xc3,0x62,0x24,0x87,
0x06
};
*keyLength=sizeofcaKey;
/*CopytoSDKbuffer.*/
Copy(buffer,caKey,(*keyLength<bufferLength)?
*keyLength:bufferLength);
01.12.2016
7/13
}
externvoidGetSignature(uint8_tbuffer[],size_tbufferLength,
size_t*signatureLength){
constuint8_tsignature[]={
0x30,0x46,0x02,0x21,0x00,0x16,0x09,0x7d,
0x01,0x50,0x53,0x68,0xb0,0x83,0xaa,0x47,
0xa0,0xec,0x29,0x4c,0x32,0x68,0x76,0x75,
0x98,0xa2,0x96,0x43,0xcd,0x1b,0x88,0x71,
0x46,0xe2,0x55,0xbd,0x89,0x02,0x21,0x00,
0x85,0x14,0x22,0xd5,0xc7,0x11,0x68,0xd0,
0x3a,0x19,0x74,0xdb,0x02,0xe1,0xee,0x31,
0x09,0xd3,0x29,0x6b,0xe0,0xd8,0x15,0x8f,
0x8e,0x71,0x22,0xa5,0xd7,0x87,0x7b,0x13
};
*signatureLength=sizeofsignature;
/*CopytoSDKbuffer.*/
Copy(buffer,signature,(*signatureLength<bufferLength)?
*signatureLength:bufferLength);
}
CLI
O smw-com-cli uma ferramenta de apoio disponvel para as plataformas Linux e Windows, que permite verificar a comunicao
com medidores da famlia SMW. Um dos principais objetivos do CLI mostrar como o SDK pode ser utilizado para realizar a leitura
e escrita de parmetros do medidor atravs de uma sesso segura e totalmente transparente para o desenvolvedor.
01.12.2016
8/13
Compilao
Esta biblioteca possui Makefile para diversos targets. A sada para qualquer target sempre gerada no diretrio Build.
Instrues para compilao:
Linux
[richard@arch-linuxtrunk]$make
ou
[richard@arch-linuxtrunk]$makeDISTRO=arch
Itron Cross-compilation
[richard@arch-linuxtrunk]$makeDISTRO=itron
Nota: Necessita do Buildroot com ucLibc. Deve ser configurado com gcc-4.8.3 e uclibc-0.9.33.2.
Windows
C:\Development\Workspace\shared\ModbusClient\trunk>make
Modos de Exibio
O CLI permite a exibio dos resultados em modo hexadecimal (corresponde ao payload da resposta Modbus do medidor), ou em
modo pretty (fcil compreenso).
Modo PRETTY
Para habilitar o modo pretty, digite a seguinte linha de comando:
[smw200i]$prettymode
E para desabilitar:
[smw200i]$noprettymode
Mtodo GET
01.12.2016
9/13
Este mtodo pode ser utilizado para recuperar valores de atributos do medidor. Uma lista de atributos e a resposta esperada so
detalhados nos tpicos adiante. A descrio das respostas para o modo decimal. Para facilitar a compreenso, o usurio pode
ativar o Modo PRETTY.
Identificador do Dispositivo
Retorna informaes do fabricante, famlia e modelo do medidor, bem como verso do firmware.
Comando:
[smw200i]$getid
Resposta:
010100000300035745470108534d5733303000000204302e303000
||_________|||______________________|
|fabricante|modelo
||tamanhodocampomodelo
|tamanhodocampofabricante
Interpretao da resposta:
Para obter os valores, deve-se converter os intervalos de informaes para string. No exemplo, o fabricante de 3 caracteres e
corresponde a "WEG" em ASCII. O modelo "SMW300".
Mais informaes sobre a resposta da funo ID podem ser encontradas aqui.
Relgio
O valor lido contm a data e a hora atuais do medidor.
O formato da resposta ddmmyyhhMMss.
Comando:
[smw200i]$getclock
Resposta:
0000040a0c151418
||||||minuto
|||||segundo
||||hora
|||ano
||ms
|dia
Interpretao da resposta:
Para obter os valores, basta visualizar o byte correspondente na forma decimal.
Tenso RMS Instantnea
O valor lido em milivolts (mV).
O medidor sempre retorna o valor correspondente de trs fases. Caso seja um medidor bifsico ou monofsico, as fases no
presentes retornam valor zero.
Comando:
01.12.2016
10/13
[smw200i]$getvoltage
Resposta:
0000000000034eac00000000000000000000000000000000
|_______________________|_______________________|_______________________|
tensoL1tensoL2tensoL3
Interpretao da resposta:
Para obter o valor de tenso, deve-se inverter a ordem do sub-array correspondente a fase desejada e convert-lo para um nmero
do tipo uint64_t.
Rel de corte e religamento
Permite abrir ou fechar o contato do rel.
Permite ler o estado atual do rel.
Ler o estado do rel
Comando:
[smw200i]$getbreaker
Resposta:
0000000000000000
|
|00=aberto,01=fechado
Interpretao da resposta:
Para saber se est aberto ou fechado, deve-se ler o valor do ltimo byte.
Mtodo SET
Este mtodo pode ser utilizado para configurar atributos do medidor. Para facilitar a compreenso, o usurio pode ativar o Modo
PRETTY.
Abrir o contato do rel
Comando:
[smw200i]$setbreakeropened
Resposta:
970004
||
||04=sucesso
|respostadocomandodeabertura
01.12.2016
11/13
Interpretao da resposta:
Sempre que o comando for executado corretamente o retorno ser o da resposta acima. Qualquer outra resposta significa que a
ao no foi executada.
Fechar o contato do rel
Comando:
[smw200i]$setbreakerclosed
Resposta:
960004
||
||04=sucesso
|respostadocomandodefechamento
Interpretao da resposta:
Sempre que o comando for executado corretamente o retorno ser o da resposta acima. Qualquer outra resposta significa que a
ao no foi executada.
Tabela de comandos
Mtodo
Atributo
Descrio
Ajuda.
exit
Encerrar a aplicao.
upgrade <filepath>
set
timeout
get
current
get
voltage
get | set
clock
Data e hora.
get
id
Identificador do dispositivo.
get | set
get
phase angle
get
frequency
Frequncia da rede.
get
get
battery status
get
temperature
get
events
Alarmes e erros.
get
get
ids
get
version
get
power factor
01.12.2016
12/13
get
thd
get
tariff zone
Arquivos
screenshot.png
43,9 KB
28.10.2015
interfaces.png
41,5 KB
29.10.2015
screenshot.png
53,5 KB
10.11.2015
cli_ethernet_udp.png
43,2 KB
21.01.2016
01.12.2016
13/13