Jump to content

Axpert 5KVA Watchpower monitoring software


Go to solution Solved by scottwday,

Recommended Posts

The older Axperts have the RJ45 RS232 ports, whereas the newer models are USB (plug and play).

Will your software be compatible with both ?.

 

The USB port on the newer models is a Serial -> USB converter.

 

I confirmed this by dmesg and lsusb on my Linux machine.

 

The issue is this:

The serial -> USB converter used by Axpert is a low cost part that is not well supported.

It has support in Windows but not in other OSs from what I can see.

 

So yes, any software will still work with the USB port provided

1) The driver is installed so that the USB port is recognized as a Serial -> USB converter

2) You point the code to the virtual serial port created by the USB.

 

As I said however, your other option is to keep using the rs232 port (which uses a RJ45/8P8C connector) and use your own serial -> USB converter or try get the USB port on the newer Axpert's working.

 

The most widely supported serial -> USB converter is a prolific part. This one happens to use that chip also: http://www.takealot.com/trendnet-usb-to-serial-converter/PLID29271821

 

But many of the serial -> USB converters make use of the prolific converter.

 

It has out of the box support for just about every Linux (including Raspberry Pi) and Mac + Windows have easy to install drivers.

 

Hence my not bothering to try get this silly Axpert converter working.

Link to post
Share on other sites
  • Replies 75
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Popular Posts

.....and then you going distribute to your mates  and forumites. I can see the data on my setup and can download it as a pdf but cannot convert it to something useful (A csv file would have been good

Watchpower is an unfortunate name I think. Too close to WatchTower. No offence to any JWs :-)

I'm a programmer so I am trying to find a RS 232 packet sniffer. I will then get all the requests and responses and map them. I will then write my own app for windows and for web including a way to c

Posted Images

I fed my C# CRC code through an automatic code converter... Who knows, maybe it'll work :)

Imports System.Collections.GenericImports System.LinqImports System.TextImports System.Threading.TasksNamespace InverterEmulator	''' <summary>	''' Calculates the CRC for the inverter	''' </summary>	Public Class CRC16		''' <summary>		''' Ported from crc.c: http://forums.aeva.asn.au/forums/pip4048ms-inverter_topic4332_page2.html		''' </summary>		Public Shared Function Calculate(pin As Byte()) As UShort			Dim crc As UShort			Dim da As Byte			'INT8U far *ptr;			Dim ptr As Byte			Dim bCRCHign As Byte			Dim bCRCLow As Byte			Dim len As Integer = pin.Length			Dim crc_ta As UShort() = New UShort() {&H0, &H1021, &H2042, &H3063, &H4084, &H50a5, _				&H60c6, &H70e7, &H8108, &H9129, &Ha14a, &Hb16b, _				&Hc18c, &Hd1ad, &He1ce, &Hf1ef}			crc = 0			For index As Integer = 0 To len - 1				ptr = pin(index)				da = CByte(CByte(crc >> 8) >> 4)				crc <<= 4				crc = crc Xor crc_ta(da Xor (ptr >> 4))				da = CByte(CByte(crc >> 8) >> 4)				crc <<= 4				crc = crc Xor crc_ta(da Xor (ptr And &Hf))			Next			'Escape CR,LF,'H' characters			bCRCLow = CByte(crc And &Hff)			bCRCHign = CByte(crc >> 8)			If bCRCLow = &H28 OrElse bCRCLow = &Hd OrElse bCRCLow = &Ha Then				bCRCLow += 1			End If			If bCRCHign = &H28 OrElse bCRCHign = &Hd OrElse bCRCHign = &Ha Then				bCRCHign += 1			End If			crc = CUShort(CUShort(bCRCHign) << 8)			crc = crc Or bCRCLow			Return crc		End Function	End ClassEnd Namespace

Although, if you just want to request messages you could hard code the CRC into the request.

 

I fed my C# CRC code through an automatic code converter... Who knows, maybe it'll work :)

Imports System.Collections.GenericImports System.LinqImports System.TextImports System.Threading.TasksNamespace InverterEmulator	''' <summary>	''' Calculates the CRC for the inverter	''' </summary>	Public Class CRC16		''' <summary>		''' Ported from crc.c: http://forums.aeva.asn.au/forums/pip4048ms-inverter_topic4332_page2.html		''' </summary>		Public Shared Function Calculate(pin As Byte()) As UShort			Dim crc As UShort			Dim da As Byte			'INT8U far *ptr;			Dim ptr As Byte			Dim bCRCHign As Byte			Dim bCRCLow As Byte			Dim len As Integer = pin.Length			Dim crc_ta As UShort() = New UShort() {&H0, &H1021, &H2042, &H3063, &H4084, &H50a5, _				&H60c6, &H70e7, &H8108, &H9129, &Ha14a, &Hb16b, _				&Hc18c, &Hd1ad, &He1ce, &Hf1ef}			crc = 0			For index As Integer = 0 To len - 1				ptr = pin(index)				da = CByte(CByte(crc >> 8) >> 4)				crc <<= 4				crc = crc Xor crc_ta(da Xor (ptr >> 4))				da = CByte(CByte(crc >> 8) >> 4)				crc <<= 4				crc = crc Xor crc_ta(da Xor (ptr And &Hf))			Next			'Escape CR,LF,'H' characters			bCRCLow = CByte(crc And &Hff)			bCRCHign = CByte(crc >> 8)			If bCRCLow = &H28 OrElse bCRCLow = &Hd OrElse bCRCLow = &Ha Then				bCRCLow += 1			End If			If bCRCHign = &H28 OrElse bCRCHign = &Hd OrElse bCRCHign = &Ha Then				bCRCHign += 1			End If			crc = CUShort(CUShort(bCRCHign) << 8)			crc = crc Or bCRCLow			Return crc		End Function	End ClassEnd Namespace

Although, if you just want to request messages you could hard code the CRC into the request.

 

Here's a capture of the traffic between WatchPower and the inverter, just copy/paste in the request strings and you should be good to go.

https://github.com/scottwday/InverterEmulator/blob/master/doc/Capture.txt?raw=true

 

 

Here's a capture of the traffic between WatchPower and the inverter, just copy/paste in the request strings and you should be good to go.

https://github.com/scottwday/InverterEmulator/blob/master/doc/Capture.txt?raw=true

 

Hi Scottwday

 

I am a c# devleoper but unfortunatley have not worked with serial ports that much. I have had an issue where I write to the port with a loop back serial tester and it triggers my event handler, however when the port is plugged into the inverter it does not trigger the event handler in c#. I can see through "serial port monitor 6 that it did write to the " port. I have downloaded the emulater from github site and I have even decompiled the watch power app which is written in java.

 

For example C#

 

 SerialPort sp = new SerialPort();

 

I then set all the required port settings

 

Then I write to the port for example

 

sp.Write(new byte[] = ({hex, hex, hex}, 0,2); // This gives me the correct write status on my port sniffer ie exactly the same as  when I sniff the port when watch power is running.

 

Do you have a snippet of hwo the port is written to or an idea why it does not trigger my event handler.

 

Thanks :)

Link to post
Share on other sites

Hi Scottwday

 

I am a c# devleoper but unfortunatley have not worked with serial ports that much. I have had an issue where I write to the port with a loop back serial tester and it triggers my event handler, however when the port is plugged into the inverter it does not trigger the event handler in c#. I can see through "serial port monitor 6 that it did write to the " port. I have downloaded the emulater from github site and I have even decompiled the watch power app which is written in java.

 

For example C#

 

 SerialPort sp = new SerialPort();

 

I then set all the required port settings

 

Then I write to the port for example

 

sp.Write(new byte[] = ({hex, hex, hex}, 0,2); // This gives me the correct write status on my port sniffer ie exactly the same as  when I sniff the port when watch power is running.

 

Do you have a snippet of hwo the port is written to or an idea why it does not trigger my event handler.

 

Thanks :)

 

The inverter will only reply once it receives a CR (0x0d) character.

 

The last argument to SerialPort.Write is the number of bytes to write. you're always going to need to write more than 2 bytes. In fact it's always going to be 3 more bytes than the command you want to send:

 

The format is <command><CRC_MSB><CRC_LSB><CR>

public byte[] GetBytes(string Command, ushort Crc){    byte[] result = new byte[Command.Length + 3];    Encoding.ASCII.GetBytes(Command, 0, Command.Length, result, 0);    result[result.Length - 3] = (byte)((Crc >> 8) & 0xFF);    result[result.Length - 2] = (byte)((Crc >> 0) & 0xFF);    result[result.Length - 1] = 0x0d;    return result;}

This code packs the bytes to send. First it's the bytes from a string, then 2 bytes of the 16 bit CRC, then a CR character.

 

If you look at the CRC code it makes sure that it never uses 0x0d or 0x0a because they are characters that denote the end of the command.

Link to post
Share on other sites

The inverter will only reply once it receives a CR (0x0d) character.

 

The last argument to SerialPort.Write is the number of bytes to write. you're always going to need to write more than 2 bytes. In fact it's always going to be 3 more bytes than the command you want to send:

 

The format is <command><CRC_MSB><CRC_LSB><CR>

public byte[] GetBytes(string Command, ushort Crc){    byte[] result = new byte[Command.Length + 3];    Encoding.ASCII.GetBytes(Command, 0, Command.Length, result, 0);    result[result.Length - 3] = (byte)((Crc >> 8) & 0xFF);    result[result.Length - 2] = (byte)((Crc >> 0) & 0xFF);    result[result.Length - 1] = 0x0d;    return result;}

This code packs the bytes to send. First it's the bytes from a string, then 2 bytes of the 16 bit CRC, then a CR character.

 

If you look at the CRC code it makes sure that it never uses 0x0d or 0x0a because they are characters that denote the end of the command.

 

Hi Still not winning :(

Still cannot get a response.

 

Here is my code

using System;using System.Collections.Generic;using System.IO.Ports;using System.Linq;using System.Text;using System.Threading.Tasks;using Microsoft.VisualBasic;using CrC;namespace ConsoleApp{    class Test1    {        /// <summary>        /// Test1        /// </summary>        public void test1()        {            /// sp.Write(new byte[] { 0x51, 0x50, 0x49, 0x47, 0x53, 0xb7, 0xa9, 0x0d }, 0, 7);            ///first command sent after port opened            /// 0x51, 0x50, 0x49, 0xbe, 0xac, 0x0d             SerialPort sp = new SerialPort();            sp.PortName = "COM3";            sp.BaudRate = 19200;            sp.DataBits = 8;            sp.Parity = Parity.None;            sp.StopBits = StopBits.One;            //   sp.Open();            sp.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);            sp.ErrorReceived += new SerialErrorReceivedEventHandler(DataErrorReceivedHandler);            byte[] val = new byte[] { 0x51, 0x50, 0x49, 0xbe, 0xac, 0x0d };            ushort uShortValue = CRC16.Calculate(val);            byte[] tx = GetBytes("QPI", uShortValue);            sp.Write(tx, 0, tx.Length);        }        public byte[] GetBytes(string Command, ushort Crc)        {            byte[] result = new byte[Command.Length + 3];            Encoding.ASCII.GetBytes(Command, 0, Command.Length, result, 0);            result[result.Length - 3] = (byte)((Crc >> 8) & 0xFF);            result[result.Length - 2] = (byte)((Crc >> 0) & 0xFF);            result[result.Length - 1] = 0x0d;            return result;        }        public void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)        {            // VALUES ARE RECEIVED IN HEX            SerialPort sp = (SerialPort)sender;            object indata = sp.ReadExisting();            Console.Write("RESPONSE : " + indata + Constants.vbCr);            Console.ReadLine();        }        public void DataErrorReceivedHandler(object sender, SerialErrorReceivedEventArgs e)        {            Console.Write(e.EventType);            Console.ReadKey();        }    }}
Link to post
Share on other sites

 

Hi Still not winning :(

Still cannot get a response.

 

Here is my code

using System;using System.Collections.Generic;using System.IO.Ports;using System.Linq;using System.Text;using System.Threading.Tasks;using Microsoft.VisualBasic;using CrC;namespace ConsoleApp{    class Test1    {        /// <summary>        /// Test1        /// </summary>        public void test1()        {            /// sp.Write(new byte[] { 0x51, 0x50, 0x49, 0x47, 0x53, 0xb7, 0xa9, 0x0d }, 0, 7);            ///first command sent after port opened            /// 0x51, 0x50, 0x49, 0xbe, 0xac, 0x0d             SerialPort sp = new SerialPort();            sp.PortName = "COM3";            sp.BaudRate = 19200;            sp.DataBits = 8;            sp.Parity = Parity.None;            sp.StopBits = StopBits.One;            //   sp.Open();            sp.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);            sp.ErrorReceived += new SerialErrorReceivedEventHandler(DataErrorReceivedHandler);            byte[] val = new byte[] { 0x51, 0x50, 0x49, 0xbe, 0xac, 0x0d };            ushort uShortValue = CRC16.Calculate(val);            byte[] tx = GetBytes("QPI", uShortValue);            sp.Write(tx, 0, tx.Length);        }        public byte[] GetBytes(string Command, ushort Crc)        {            byte[] result = new byte[Command.Length + 3];            Encoding.ASCII.GetBytes(Command, 0, Command.Length, result, 0);            result[result.Length - 3] = (byte)((Crc >> 8) & 0xFF);            result[result.Length - 2] = (byte)((Crc >> 0) & 0xFF);            result[result.Length - 1] = 0x0d;            return result;        }        public void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)        {            // VALUES ARE RECEIVED IN HEX            SerialPort sp = (SerialPort)sender;            object indata = sp.ReadExisting();            Console.Write("RESPONSE : " + indata + Constants.vbCr);            Console.ReadLine();        }        public void DataErrorReceivedHandler(object sender, SerialErrorReceivedEventArgs e)        {            Console.Write(e.EventType);            Console.ReadKey();        }    }}

 

I haven't tested your code, but at first glance it should be 2400 baud

Link to post
Share on other sites

I wrote a library in Ruby which simplifies the whole communication.

 

Ruby is cross platform (eg. Windows, Linux, Mac) and you would only need to install:

 

Ruby

Ruby-gems

 

Then install the following gems:

 

serialport

axpert_rs232

 

Both are documented and supported on ALL OSs (Worked for me on both my Mac and Raspberry Pi)

 

I'm super busy at work so I haven't been able to finish my application which would give you a web front-end for that library.

 

I tested it using a USB -> Serial converter and I'm still using it.

 

At this point what I have is:

I wrote an application that dumps the Axpert current device status every 2 seconds into a file.

This file keeps being updated and rotate every hour.

Then I used a simple web-application that polls that file for changes and makes it available.

Lastly I used a simple AJAX call with a static HTML page and chart.js to draw some data.

 

All of it is very hacky at this point so I don't want to release it yet.

 

But when I'm done hopefully you can get a web interface of your power usage over time. When you were on battery and when on grid power.

How much is being used by what.

What are the temperatures

Emails when you go on grid/off grid/loss of grid.

 

Nice pretty graphs for everything.

 

The HTML part takes a really long time to be honest and it bogs me down :(

 

On my Raspberry Pi I installed it as follows:

sudo apt-get install ruby-dev

sudo gem install serialport

sudo gem install axpert_rs232

 

After that everything was working.

 

On my Mac I didn't need to do anything except install serialport and axpert_rs232.

 

Haven't tested on Windows (honestly I'm lazy, I hardly use Windows anymore)

Can it do data logging, over time?

Link to post
Share on other sites

The older Axperts have the RJ45 RS232 ports, whereas the newer models are USB (plug and play).

Will your software be compatible with both ?.

 

It's not a new model it's the same model, they only swap out the interface board to USB. If you buy the remote unit it comes with a RJ45 board which you swop out with your USB board. I prefer RJ45, I have my remote unit running 20m ovet CAT5E to my office then you simply run a serial to USB into PC from the remote.

 

http://www.geewiz.co.za/inverters/12720-axpert-remote-control-panel.html

post-1034-0-05022400-1442604020_thumb.jp

post-1034-0-06919500-1442604022_thumb.jp

post-1034-0-32149900-1442604298_thumb.jp

Link to post
Share on other sites

No luck with 2400

 

You have sp.Open commented out as well.

 

I've put a simple C# command line utility on my github which lets you send a command and prints out the response.

It handles all the CRC stuff. It might also be useful for anyone wanting to use it from scripts etc.

 

Eg:

console>AxpertTest -p COM3 QPI(PI30console>AxpertTest -p COM3 QPIGS(244.2 49.9 244.2 49.9 0024 0015 000 435 54.00 001 100 0019 0000 000.0 00.00 00000 00010101 00 00 00000 110

You can also set the baud (-B) and the timeout in milliseconds (-t)

 

Here'e the .exe binary

https://drive.google.com/file/d/0B8CTDo4cVxUlYzFZWnYtYlVETFE/view?usp=sharing

 

Here's the sourcecode

https://github.com/scottwday/AxpertTest/blob/master/Program.cs

 

I've tested it works on my inverter (~2014 model) and with my emulator

Link to post
Share on other sites

You have sp.Open commented out as well.

 

I've put a simple C# command line utility on my github which lets you send a command and prints out the response.

It handles all the CRC stuff. It might also be useful for anyone wanting to use it from scripts etc.

 

Eg:

console>AxpertTest -p COM3 QPI(PI30console>AxpertTest -p COM3 QPIGS(244.2 49.9 244.2 49.9 0024 0015 000 435 54.00 001 100 0019 0000 000.0 00.00 00000 00010101 00 00 00000 110

You can also set the baud (- B) and the timeout in milliseconds (-t)

 

Here'e the .exe binary

https://drive.google.com/file/d/0B8CTDo4cVxUlYzFZWnYtYlVETFE/view?usp=sharing

 

Here's the sourcecode

https://github.com/scottwday/AxpertTest/blob/master/Program.cs

 

I've tested it works on my inverter (~2014 model) and with my emulator

 

Hi scottwday

 

I got it to send the command and trigger the event handler. Now comes the fun part to extrapolate the data. Thanks for your help. It made a big difference.

 

Your code snippet was very helpful :)

public byte[] GetBytes(string Command, ushort Crc){    byte[] result = new byte[Command.Length + 3];    Encoding.ASCII.GetBytes(Command, 0, Command.Length, result, 0);    result[result.Length - 3] = (byte)((Crc >> 8) & 0xFF);    result[result.Length - 2] = (byte)((Crc >> 0) & 0xFF);    result[result.Length - 1] = 0x0d;    return result;}
Link to post
Share on other sites

It's not a new model it's the same model, they only swap out the interface board to USB. If you buy the remote unit it comes with a RJ45 board which you swop out with your USB board. I prefer RJ45, I have my remote unit running 20m ovet CAT5E to my office then you simply run a serial to USB into PC from the remote.

 

http://www.geewiz.co.za/inverters/12720-axpert-remote-control-panel.html

Where do you get the USB board? geewiz doesn't sell them anymore

Link to post
Share on other sites

So I am making progress with re-writing the watchpower application for the axpert with the RJ45 to serial option. I do still have one issue.There is a option to view data which is working great however the option for view event log does not seem to work. I cannot select the device ID. I have checked the the inverter and I have set option 25 to enable event logging but to no avail.

 

Has anybody else had the same issue or an idea why it does not work?

 

Can anybody else access there Event log and see data?

Link to post
Share on other sites

Hi all. I do hope somebody can help me as I have been trying to get this working for 2 days now and can not explain what is going on.

 

I used a sniffer to find the commands that go the the inverters that include the CRC characters. Not going to work them out as they stay the same.

But the inverters are ignoring me. Please watch the video to see what I am getting. I hope somebody can help me as this is very strange,

 

 

 

Are you sure the baud and parity are set correctly in your VB app? It should be 2400 baud, no parity, 8 data bits, 1 stop bit

Link to post
Share on other sites

This is a test app. Just to see if the inverters answer. I had to change the serial port encoding to get the correct string to come out on the serial port. I have also de complied the WatchPower software to see how it works.

 

 

Here is the code of the little app

 

 

Imports System

Imports System.Threading

Imports System.IO.Ports

Imports System.ComponentModel

Imports System.Collections.Generic

Public Class Form1

    Delegate Sub SetTextCallback(ByVal [text] As String) 'Added to prevent threading errors during receiveing of data

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

       

        SerialPort1.Encoding = System.Text.Encoding.GetEncoding(1252)

        SerialPort1.Open()

    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        Dim serialcommand As String

        serialcommand = "QPGS0?

Link to post
Share on other sites

I looked at it now. I do not believe the serial port control when dragged onto a form automatically creates an event handler. When you start your program it starts on one thread. The reply comes from the second thread. So yes you are getting a reply, however not on the same thread. That is why you need an eventhandler below. Remember your application text box is linked to the first thread and the response is on the second thread. Threads cannot write directly to each other. Rather use the SerialPort Class that comes with .net 4. I have not seen a coms control in a long time so I am sure te control is pretty old

 

It looks like you are using VB 6 or you have downloaded a 3rd party coms ocx, dll or activex control.

sp.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);//This allows you to write from one thread to another. Basically to populate a text boxdelegate void SetTextCallback(string text);public void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)        {            string rx = null;            SerialPort sp = (SerialPort)sender;            while (sp.BytesToRead > 0)            {                rx += sp.ReadExisting().ToString();            }            if (!string.IsNullOrEmpty(rx))            {                SetText(rx);            }
Link to post
Share on other sites

The other possibility is and I'm assuming you are using a sub to rs232 connector is that I have heard dome of them don't work properly but then again you are receiving data back with the coms sniffer. I cannot think of anything else. Sorry. I hope you get it right as I struggled too for a few days till Scott helped me figure it out. ?

Link to post
Share on other sites

Hi guys. I am no programmer and understand zilch of the expert advise above. I do know though that the Watchpower software is totally inadequate for the purpose it was designed for. Are there any of you bright programming whizz kids that have come up with something better one can use?

Link to post
Share on other sites

Hi guys. I am no programmer and understand zilch of the expert advise above. I do know though that the Watchpower software is totally inadequate for the purpose it was designed for. Are there any of you bright programming whizz kids that have come up with something better one can use?

 

The bun is in the oven so to speak.

Link to post
Share on other sites

OK Warren you were correct. I had to add the data receiver proc to make it work. Very strange that you have to add that part as lets say I just want to send data and not receive any.

But at least now I am talking to the inverters and now I can build the rest of the software. Let the fun begin ;-)

 

Thats great I am glad I could assist as it is frustrating when you are stuck. I am now stuck with the problem where the eventhandler sometimes reads only half the data for example

 

Protocol QPIGS request

 

(000.0 00.0 230.3 50.0 0298 0228 005 408

 

where it is supposed to return

 

(000.0 00.0 230.3 50.0 0298 0228 005 408 50.80 000 086 0049 0000 054.6 50.74 00004 00010110 00 00 00010 110?`

 

I know why it does it just not sure how to get around it. It reads the receive buffer before it has completed buffering. So I need to find a way to see when the response is complete. I think it has to DTR but I need to do some more research

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...