Gnome 116 Posted September 15, 2015 Share Posted September 15, 2015 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. Quote Link to post Share on other sites
Warren 3 Posted September 17, 2015 Author Share Posted September 17, 2015 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 Quote Link to post Share on other sites
scottwday 3 Posted September 18, 2015 Share Posted September 18, 2015 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. Warren 1 Quote Link to post Share on other sites
Warren 3 Posted September 18, 2015 Author Share Posted September 18, 2015 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(); } }} Quote Link to post Share on other sites
scottwday 3 Posted September 18, 2015 Share Posted September 18, 2015 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 Quote Link to post Share on other sites
Warren 3 Posted September 18, 2015 Author Share Posted September 18, 2015 I haven't tested your code, but at first glance it should be 2400 baud let me try that. Its wierd when I run it through waqtchpower it connects a 19200 Quote Link to post Share on other sites
Warren 3 Posted September 18, 2015 Author Share Posted September 18, 2015 let me try that. Its wierd when I run it through waqtchpower it connects a 19200 No luck with 2400 Quote Link to post Share on other sites
SilverNodashi 760 Posted September 18, 2015 Share Posted September 18, 2015 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? Quote Link to post Share on other sites
Alex 3 Posted September 18, 2015 Share Posted September 18, 2015 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 Quote Link to post Share on other sites
scottwday 3 Posted September 19, 2015 Share Posted September 19, 2015 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 (- 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 Quote Link to post Share on other sites
Warren 3 Posted September 20, 2015 Author Share Posted September 20, 2015 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 (- 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;} Quote Link to post Share on other sites
krugeran58 2 Posted September 20, 2015 Share Posted September 20, 2015 Hi do you guys have watchpower program to work when running from console R45 port on remote box. On mine it doesn't show inveter. Inverter only show if I disconnect remote box and connect directly to inveter comm-board rs-232 RJ45 port. Quote Link to post Share on other sites
SilverNodashi 760 Posted September 24, 2015 Share Posted September 24, 2015 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 Quote Link to post Share on other sites
Eugene 20 Posted September 24, 2015 Share Posted September 24, 2015 Where do you get the USB board? geewiz doesn't sell them anymore The newer inverters have the USB interface, the RS232 is required for the Remote Panel. The RS232 card is not bundled with Remote Panel and has to be purchased separately. https://onedrive.live.com/redir?resid=B6E11F173DB13421!1820&authkey=!ALinbGasIQFRUSI&ithint=file%2cpdf Quote Link to post Share on other sites
Warren 3 Posted September 24, 2015 Author Share Posted September 24, 2015 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? Quote Link to post Share on other sites
scottwday 3 Posted September 29, 2015 Share Posted September 29, 2015 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 Quote Link to post Share on other sites
scottwday 3 Posted September 29, 2015 Share Posted September 29, 2015 Yes. The sniffer shows you what all your connection settings are also. Can you post your code? Quote Link to post Share on other sites
Warren 3 Posted September 30, 2015 Author Share Posted September 30, 2015 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? Quote Link to post Share on other sites
Warren 3 Posted September 30, 2015 Author Share Posted September 30, 2015 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); } Quote Link to post Share on other sites
Warren 3 Posted September 30, 2015 Author Share Posted September 30, 2015 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. ? Quote Link to post Share on other sites
edmundp 109 Posted September 30, 2015 Share Posted September 30, 2015 O for the love of Pete! I will pay you all to do this! I know at least one other non forumite that will pay for a decent app perhaps integrating victron bmv readings. Must do aggregate calcs as well and graphing. Like seriously man. ___ 1 Quote Link to post Share on other sites
scottwday 3 Posted October 1, 2015 Share Posted October 1, 2015 Sorry Jdp, I'm also stumped Quote Link to post Share on other sites
Deonsr 6 Posted October 3, 2015 Share Posted October 3, 2015 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? Quote Link to post Share on other sites
Chris Hobson 1,777 Posted October 3, 2015 Share Posted October 3, 2015 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. Quote Link to post Share on other sites
Warren 3 Posted October 5, 2015 Author Share Posted October 5, 2015 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 Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.