Before commenting read Forum rules
Don't comment the topic if you have a new question.
You can create a new topic selecting correct category from Gurux Forum and then create a new topic selecting "New Topic" from the top left.
Before commenting read Forum rules
Don't comment the topic if you have a new question.
You can create a new topic selecting correct category from Gurux Forum and then create a new topic selecting "New Topic" from the top left.
I have looked at the sample provided for c# at
http://www.gurux.org/gxdn/GXDLMS/samplecode.html
and the code provided at
http://www.gurux.fi//node/252
The samples work great for establishing a handshake with the meter, and getting a reply. Where my problem comes in is at the ReadDLMSPacket part. It goes into the method, but with the first SendSync command, it always times out, no matter the length of WaitTime. DLMSDirector reads my meter fine, so it must be in my code somewhere.
Below is the code I'm currently using :
using System;
using System.Windows.Forms;
using Gurux.DLMS2;
using Gurux.Serial;
namespace DLMSTest
{
public partial class FrmMain : Form
{
// Device reply wait time.
int WaitTime = 5;
private CGXCOSEMClass m_Cosem;
private GXSerial serial;
public FrmMain()
{
InitializeComponent();
m_Cosem = new CGXCOSEMClass {ClientID = 0x10, ServerID = 0x1, UseLogicalNameReferencing = true};
}
private void btnConnect_Click(object sender, EventArgs e)
{
QueryMeter();
}
private object ReadDLMSPacket(object data)
{
if (data == null)
{
return null;
}
object reply = null;
byte Terminator = 0x7E;
if (!serial.SendSync(data, Gurux.Common.VariantType.None, Terminator, 5, WaitTime * 1000, false, Gurux.Common.VariantType.Array | Gurux.Common.VariantType.UInt8, out reply))
{
throw new Exception("Failed to receive reply from the device in given time.");
}
//Loop until whole m_Cosem packet is received.
while (!m_Cosem.IsDLMSPacketComplete(reply))
{
if (!serial.WaitMoreReplyData(Terminator, 0, WaitTime, true, Gurux.Common.VariantType.Array | Gurux.Common.VariantType.UInt8, ref reply))
{
throw new Exception("Failed to receive reply from the device in given time.");
}
}
serial.SendSyncComplete = true;
return reply;
}
private void QueryMeter()
{
serial = new GXSerial {Port = "COM10"};
object reply = null;
byte Terminator = (byte)0x0A;
// Bitrate must be 300 when connection is initialized.
serial.BitRate = 9600;
serial.DataBits = ByteSize.Byte7Bits;
serial.Parity = Gurux.Serial.Parity.Even;
serial.StopBits = Gurux.Serial.StopBits.One;
serial.Open();
//Query device information.
if (!serial.SendSync("/?!\r\n", Gurux.Common.VariantType.String, Terminator, 0, WaitTime * 1000, false, Gurux.Common.VariantType.String, out reply))
{
object d = serial.GetReplyData(Gurux.Common.VariantType.HexString);
throw new Exception("Failed to receive reply from the device in given time.");
}
string answer = reply.ToString();
if (answer[0] != '/')
{
throw new Exception("Invalid responce.");
}
string manufactureID = answer.Substring(1, 3);
char baudrate = answer[4];
int bitrate = 0;
switch (baudrate)
{
case '0':
bitrate = 300;
break;
case '1':
bitrate = 600;
break;
case '2':
bitrate = 1200;
break;
case '3':
bitrate = 2400;
break;
case '4':
bitrate = 4800;
break;
case '5':
bitrate = 9600;
break;
case '6':
bitrate = 19200;
break;
default:
throw new Exception("Unknown baud rate.");
}
//Send ACK
//Send Protocol control character
byte controlCharacter = (byte)'2';// "2" HDLC protocol procedure (Mode E)
//Send Baudrate character
//Mode control character
byte ModeControlCharacter = (byte)'2';//"2" //(HDLC protocol procedure) (Binary mode)
//Set mode E.
serial.SendSync(new byte[] { 0x06, controlCharacter, (byte)baudrate, ModeControlCharacter, 13, 10 }, Gurux.Common.VariantType.None, Terminator, 0, 500, false, Gurux.Common.VariantType.Array | Gurux.Common.VariantType.UInt8, out reply);
serial.BitRate = bitrate;
serial.DataBits = ByteSize.Byte8Bits;
serial.Parity = Gurux.Serial.Parity.None;
serial.StopBits = Gurux.Serial.StopBits.One;
object data;
data = m_Cosem.SNRMRequest();
reply = ReadDLMSPacket(data);
//Has server accepted client.
m_Cosem.ParseUAResponse(reply);
//Generate AARQ request.
data = m_Cosem.AARQRequest(null);
//Split regusts to multible packets if needed.
//This must be done because all data might not be fit in one packet if password is used.
Array arr = (Array)m_Cosem.SplitDataToPackets(data);
int len = arr.Length;
int pos = 0;
foreach (byte[] it in arr)
{
data = it;
data = m_Cosem.Read(data, ++pos, len, ObjectType.None, 0);
reply = ReadDLMSPacket(data);
}
//Parse reply.
m_Cosem.ParseAAREResponse(reply);
}
}
}
So, the problem comes in the ReadDLMSPacket method, with the first SendSync command. I have tried numerous combinations of ServerID and ClientID, but I'm not sure whether this is indeed the problem.
We are looking to use this component with a Commercial License (instead of coding the DLMS ourselves), but without a working prototype, I'm afraid it is of little use. Any help would be greatly appreciated!
Landis & Gyr ZMD40, c#
Hi,
Can you send the data that you try to send in SendSync?
BR,
Mikko
Hi, I've uploaded a snapshot
Hi,
I've uploaded a snapshot of the data that gets send to the ReadDLMSPacket (line 126) method here : http://imageshack.us/photo/my-images/854/requestdata.png/
This data is that gets send back from the m_Cosem.SNRMRequest() (line 125).
Here is it, just in case :
data {byte[15]}
[0] 126
[1] 160
[2] 13
[3] 0
[4] 0
[5] 0
[6] 1
[7] 0
[8] 0
[9] 0
[10] 16
[11] 147
[12] 127
[13] 189
[14] 126
thank you for the reply, and hope this helps!
Problem solved
Hi,
You must cast ClientID and serverID to byte
Like this
{ClientID = (byte)0x10, ServerID = (byte) 0x1,
BR,
Mikko
Hi, Thanks for the swift
Hi,
Thanks for the swift response!
I casted the ClientID and ServerID as directed.
The problem still persists, although, this time, the data that gets send to the ReadDlmsPacket method is different from before, but the time-out still occurs.
data {byte[9]}
[0] 126
[1] 160
[2] 7
[3] 1
[4] 16
[5] 147
[6] 205
[7] 27
[8] 126
Any ideas? Thank you!
Looks better
Hi,
Now looks better. Now you have to make client and server addresses like I have explained here: http://www.gurux.fi/node/336
Basically what you should do is shift value one to right and set lovest bit to 1. :-)
dlms.ClientID = (value 1) | 1;
dlms.ServerID = (value 1) | 1;
So client address is 0x21 and server address is 3.
Happy coding,
Mikko
A lot better, new stumble block
Hi!
Your suggestion worked like a charm!
It now runs all the way through to the very last line (line 145) :
//Parse reply.
m_Cosem.ParseAAREResponse(reply);
At this point, it has parsed the UA response, generated a AARQRequest, Split it into data packets (which it only had one of), and constructed a reply from the code below :
foreach (byte[] it in arr)
{
data = it;
data = m_Cosem.Read(data, ++pos, len, ObjectType.None, 0);
reply = ReadDLMSPacket(data);
}
After this, the ParseAAREResponse gets called. I get a UNKNOWN ERROR from your BugTrap Information.
The reply that gets passed to the ParseAAREResponse, looks as follows :
replay {byte[56]}
[0] 126
[1] 160
[2] 54
[3] 33
[4] 3
[5] 48
[6] 215
[7] 96
[8] 230
[9] 231
[10] 0
[11] 97
[12] 40
[13] 161
[14] 9
[15] 6
[16] 7
[17] 96
[18] 133
[19] 116
[20] 5
[21] 8
[22] 1
[23] 2
[24] 162
[25] 3
[26] 2
[27] 1
[28] 1
[29] 163
[30] 5
[31] 161
[32] 3
[33] 2
[34] 1
[35] 2
[36] 190
[37] 15
[38] 4
[39] 13
[40] 8
[41] 0
[42] 6
[43] 95
[44] 0
[45] 4
[46] 24
[47] 2
[48] 32
[49] 9
[50] 96
[51] 250
[52] 0
[53] 192
[54] 63
[55] 126
Thank you SO much for helping me this far! I just hope I can finally lay this to rest...
Disconnect
Hi,
You must call Disconnect -method after you have made connection to the device.
If you try to read device again after this error it should succeeded.
Remember call Disconnect method.
BR,
Mikko