521 lines
19 KiB
C#
521 lines
19 KiB
C#
using Newtonsoft.Json;
|
|
using Newtonsoft.Json.Linq;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore;
|
|
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
|
|
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore;
|
|
|
|
namespace Xylem.Common.Ui.GenesisToolBox
|
|
{
|
|
public partial class FrmLog : Form
|
|
{
|
|
public GenesisMeter _currentGenesis { get; private set; }
|
|
public MeterBatch _meterBatch { get; private set; }
|
|
|
|
public FrmLog()
|
|
{
|
|
InitializeComponent();
|
|
}
|
|
|
|
private void button1_Click(Object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private void btnConnect_Click(Object sender, EventArgs e)
|
|
{
|
|
Connect();
|
|
}
|
|
|
|
private void Connect()
|
|
{
|
|
try
|
|
{
|
|
var statusMap = new Dictionary<Int32, String>();
|
|
if (System.IO.File.Exists("Status.json"))
|
|
{
|
|
var dict = JsonConvert.DeserializeObject<Dictionary<String, JObject>>(System.IO.File.ReadAllText("Status.json"));
|
|
foreach (var item in dict)
|
|
{
|
|
statusMap.Add(int.Parse(item.Value.First.Values().First().ToString()), item.Key);
|
|
}
|
|
//var jo = JObject.Parse();
|
|
//((JObject)jo).ChildrenTokens
|
|
//var retListRealCsd = JsonConvert.DeserializeObject(<List<CsdParameterResult>>(retStr);
|
|
}
|
|
|
|
Int32 slotNr;
|
|
|
|
if (string.IsNullOrEmpty(cbComSlot.SelectedItem.ToString()) ||
|
|
!int.TryParse(cbComSlot.SelectedItem.ToString(), out slotNr))
|
|
{
|
|
return;
|
|
}
|
|
//var drive = 1;
|
|
_currentGenesis?.DisposeMeter();
|
|
//dispose old meter
|
|
_meterBatch = new MeterBatch();
|
|
_currentGenesis = null;
|
|
Thread.Sleep(200);
|
|
|
|
//assign new meter and assign meter to FW update file if this exists
|
|
_currentGenesis = new GenesisMeter();
|
|
|
|
_currentGenesis.SetupFromConfigFile(slotNr);
|
|
_meterBatch.AddMeter(_currentGenesis);
|
|
|
|
_currentGenesis._configuration.UseRegisterWatchService = false;
|
|
_currentGenesis._configuration.UseMinMaxCheck = false;
|
|
|
|
Task.Factory.StartNew(() =>
|
|
{
|
|
_meterBatch.MetersLogin();
|
|
|
|
if (!_currentGenesis.IsLoggedOn)
|
|
{
|
|
Thread.Sleep(2000);
|
|
_meterBatch.MetersLogin();
|
|
}
|
|
|
|
if (!_currentGenesis.IsLoggedOn)
|
|
{
|
|
return;
|
|
}
|
|
StringBuilder print = new StringBuilder();
|
|
|
|
|
|
print.AppendLine($"Meter time: { ByteArrayStyle.ByteStyler.ToString(_currentGenesis.ReadRegister("SYSTEM_CalendarSeconds"))}");
|
|
//flush the log files
|
|
print.AppendLine($"Flushing the logger");
|
|
_currentGenesis.WriteRegister("LOGGER_TriggerLogFlush", 1);
|
|
// read the log index
|
|
print.AppendLine($"Reading the list of log files");
|
|
|
|
var fl = get_filenames(_currentGenesis, 1);
|
|
|
|
|
|
|
|
var flHash = new HashSet<String>(fl);
|
|
fl = flHash.ToList();
|
|
var data = new Dictionary<String, List<Byte>>();
|
|
|
|
|
|
foreach (var fileName in fl)
|
|
{
|
|
|
|
print.AppendLine($"Reading the log files");
|
|
|
|
var fileData = new List<Byte>();
|
|
|
|
|
|
var listBack = new List<Byte>();
|
|
var namelist = new List<String>();
|
|
//write file name to meter with meter open command, don't wait for response
|
|
_currentGenesis.WriteRegister(Register.Configexchange.FileOpen, $"{1}\\{fileName}", false);
|
|
//write access flag
|
|
_currentGenesis.WriteRegister(Register.Configexchange.FileOpen, "r", false);
|
|
//CONFIGEXCHANGE_FOpen -> 02040400315c6c6f67696e646578000072000000
|
|
|
|
//get the file pointer
|
|
var _filePointer = RegisterConverter.ConvertTo<Int32>(_currentGenesis.ReadRegister(
|
|
Register.Configexchange.FileOpen));
|
|
|
|
_currentGenesis.WriteRegister("CONFIGEXCHANGE_FSeek", _filePointer, false);
|
|
_currentGenesis.WriteRegister("CONFIGEXCHANGE_FSeek", 0, false);
|
|
_currentGenesis.WriteRegister("CONFIGEXCHANGE_FSeek", 2, false);
|
|
|
|
|
|
|
|
_currentGenesis.WriteRegister("CONFIGEXCHANGE_FTell", _filePointer, false);
|
|
var fixedReadBackCount = RegisterConverter.ConvertTo<Int32>(_currentGenesis.ReadRegister("CONFIGEXCHANGE_FTell"));
|
|
|
|
_currentGenesis.WriteRegister("CONFIGEXCHANGE_FSeek", _filePointer, false);
|
|
_currentGenesis.WriteRegister("CONFIGEXCHANGE_FSeek", 0, false);
|
|
_currentGenesis.WriteRegister("CONFIGEXCHANGE_FSeek", 0, false);
|
|
|
|
|
|
_currentGenesis.WriteRegister("CONFIGEXCHANGE_FRead", 1, false);
|
|
_currentGenesis.WriteRegister("CONFIGEXCHANGE_FRead", fixedReadBackCount, false);
|
|
_currentGenesis.WriteRegister("CONFIGEXCHANGE_FRead", _filePointer, false);
|
|
var count_ret = RegisterConverter.ConvertTo<Int32>(_currentGenesis.ReadRegister("CONFIGEXCHANGE_FRead"));
|
|
while (count_ret != 0)
|
|
{
|
|
var numRead = 0;
|
|
//
|
|
while (numRead <= count_ret / 4)
|
|
{
|
|
var readAdd = _currentGenesis.ReadRegister("CONFIGEXCHANGE_FRead");
|
|
if (readAdd != null)
|
|
{
|
|
fileData.AddRange(readAdd);
|
|
}
|
|
numRead = numRead + 1;
|
|
}
|
|
|
|
count_ret = RegisterConverter.ConvertTo<Int32>(_currentGenesis.ReadRegister("CONFIGEXCHANGE_FRead"));
|
|
|
|
}
|
|
|
|
|
|
_currentGenesis.WriteRegister(Register.Configexchange.FileClose, _filePointer);
|
|
|
|
data.Add(fileName, fileData);
|
|
}
|
|
|
|
var loglines = new List<String>();
|
|
foreach (var item in data)
|
|
{
|
|
print.AppendLine(item.Key);
|
|
|
|
print.AppendLine($"all data: { ByteArrayStyle.ByteStyler.ToString(item.Value.ToArray())}");
|
|
|
|
|
|
if (item.Value != null && item.Value.Count >= 4)
|
|
{
|
|
var logtype = item.Value.GetRange(0, 1).First().ToString();
|
|
var status = BitConverter.ToUInt16(item.Value.GetRange(1, 2).ToArray(), 0);
|
|
var count = (Int32)BitConverter.ToUInt16(item.Value.GetRange(2, 2).ToArray(), 0);
|
|
|
|
count = count + 1;
|
|
var extradatasize = item.Value.GetRange(3, 1).First().ToString();
|
|
|
|
//var extradatasize = BitConverter.ToChar(item.Value.GetRange(3, 1).ToArray(), 0);
|
|
switch (logtype)
|
|
{
|
|
case "0":
|
|
logtype = $"({logtype}) Informational";
|
|
break;
|
|
case "1":
|
|
logtype = $"({logtype}) Warning";
|
|
break;
|
|
case "2":
|
|
logtype = $"({logtype}) Critical";
|
|
break;
|
|
}
|
|
print.AppendLine($"logtype:{logtype}");
|
|
if (statusMap.ContainsKey(status))
|
|
{
|
|
print.AppendLine($"status: ({status}) {statusMap[status]}");
|
|
}
|
|
else
|
|
{
|
|
print.AppendLine($"status:{status}");
|
|
}
|
|
print.AppendLine($"count:{count}");
|
|
|
|
print.AppendLine($"extradatasize:{extradatasize}");
|
|
var extradtalength = 0;
|
|
|
|
if (int.TryParse(extradatasize, out extradtalength))
|
|
{
|
|
print.Append("Extra data: ");
|
|
for (Int32 i = 0; i <= extradtalength; i++)
|
|
{
|
|
print.Append(item.Value.GetRange(i, 2).First().ToString("X2"));
|
|
print.Append(" ");
|
|
}
|
|
print.AppendLine();
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
print.AppendLine($"file is empty");
|
|
}
|
|
}
|
|
_currentGenesis.Logout();
|
|
Invoke(new Action(() =>
|
|
{
|
|
richTextBox1.Text = print.ToString();
|
|
}));
|
|
}).ContinueWith(delegate { ViewProgressPcb(false); });
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message);
|
|
}
|
|
}
|
|
|
|
private void ViewProgressPcb(Boolean v)
|
|
{
|
|
|
|
}
|
|
|
|
private List<String> get_filenames(GenesisMeter m, Int32 drive = 1)
|
|
{
|
|
|
|
var listBack = new List<Byte>();
|
|
var namelist = new List<String>();
|
|
//write file name to meter with meter open command, don't wait for response
|
|
m.WriteRegister(Register.Configexchange.FileOpen, $"1\\logindex", false);
|
|
//write access flag
|
|
m.WriteRegister(Register.Configexchange.FileOpen, "r", false);
|
|
//CONFIGEXCHANGE_FOpen -> 02040400315c6c6f67696e646578000072000000
|
|
|
|
//get the file pointer
|
|
var _filePointer = RegisterConverter.ConvertTo<Int32>(m.ReadRegister(
|
|
Register.Configexchange.FileOpen));
|
|
|
|
//set timeout back to default value
|
|
//CONFIGEXCHANGE_FOpen <- 030a0000584400209ae0 (536888408)
|
|
|
|
var eof = false;
|
|
|
|
while (!eof)
|
|
{
|
|
//CONFIGEXCHANGE_FEOF-> 9b2007020b0904584400207a27(XD)
|
|
m.WriteRegister("CONFIGEXCHANGE_FEOF", _filePointer, false);
|
|
|
|
//CONFIGEXCHANGE_FEOF <-030a0000000000004194 (0)
|
|
var res = RegisterConverter.ConvertTo<Int32>(m.ReadRegister("CONFIGEXCHANGE_FEOF"));
|
|
if (res != 0)
|
|
{
|
|
eof = true;
|
|
break;
|
|
}
|
|
m.WriteRegister("CONFIGEXCHANGE_FRead", 4, false);
|
|
m.WriteRegister("CONFIGEXCHANGE_FRead", 1, false);
|
|
m.WriteRegister("CONFIGEXCHANGE_FRead", _filePointer, false);
|
|
var resLength = RegisterConverter.ConvertTo<Int32>(m.ReadRegister("CONFIGEXCHANGE_FRead"));
|
|
|
|
var filecontent = m.ReadRegister("CONFIGEXCHANGE_FRead", resLength);
|
|
namelist.Add(RegisterConverter.ConvertTo<Int32>(filecontent).ToString("X8"));
|
|
|
|
}
|
|
_currentGenesis.WriteRegister(Register.Configexchange.FileClose, _filePointer);
|
|
|
|
|
|
return namelist;
|
|
}
|
|
|
|
private void label2_Click(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private void cbComSlot_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//import opticalinterface.opticalapp as oa
|
|
//import struct
|
|
//import
|
|
|
|
//import datetime
|
|
|
|
//class LogEntry(object):
|
|
// statusdict = dict()
|
|
// STATUSFILENAME = 'status.json'
|
|
|
|
// @classmethod
|
|
// def bytes_to_log(cls, filename, data) :
|
|
// logformat = "<BHBB"
|
|
// entries = list()
|
|
// while data:
|
|
// logtype, status, count, extradatasize = struct.unpack_from(logformat, data)
|
|
// data = data[struct.calcsize(logformat) :]
|
|
|
|
// # count is stored as count-1
|
|
// count += 1
|
|
// extradata = data[:extradatasize]
|
|
|
|
// entries.append(cls(filename, logtype, count, status, extradata))
|
|
|
|
// data = data[extradatasize:]
|
|
|
|
// return entries
|
|
|
|
// def __init__(self, filename, logtype, count, status, extradata=[]) :
|
|
// self.filename = filename
|
|
// self.logtype = logtype
|
|
// self.count = count
|
|
// self.status = status
|
|
// self.extradata = extradata
|
|
// self.filenametime = datetime.datetime(2000, 1, 1) + datetime.timedelta(seconds = int(filename, 16))
|
|
|
|
// def log_type_name(self):
|
|
// if self.logtype == 0:
|
|
// return "Informational"
|
|
// if self.logtype == 1:
|
|
// return "Warning"
|
|
// if self.logtype == 2:
|
|
// return "Critical"
|
|
// return "Unknown logtype"
|
|
|
|
// def status_lookup(self, status= None):
|
|
// #if the status dictionary is empty populate it
|
|
// if len(self.statusdict) == 0:
|
|
// with open(self.STATUSFILENAME) as fp:
|
|
// self.statusdict = json.load(fp)
|
|
|
|
// if status == None:
|
|
// status = self.status
|
|
|
|
// try:
|
|
// return [x for x in self.statusdict if self.statusdict[x]['id'] == status][0]
|
|
// except IndexError:
|
|
// return "Unknown status {:04X}".format(status)
|
|
|
|
// def guess_extra_data(self):
|
|
//# now try some data types to guess the extra data
|
|
// ret = list()
|
|
|
|
//# timestamp followed by uint32_t
|
|
// try:
|
|
// data = struct.unpack("<II", self.extradata)
|
|
// extraword = data[1]
|
|
// ts = datetime.datetime(2000, 1, 1) + datetime.timedelta(seconds=data[0])
|
|
// ret += ["Timestamp: {}, uint32_t: {}".format(ts, extraword)]
|
|
// except:
|
|
// pass
|
|
|
|
//# timestamp followed by status
|
|
// try:
|
|
// data = struct.unpack("<IH", self.extradata)
|
|
// status = self.status_lookup(data[1])
|
|
// ts = datetime.datetime(2000, 1, 1) + datetime.timedelta(seconds=data[0])
|
|
// ret += ["Timestamp: {}, Status: {}".format(ts, status)]
|
|
// except:
|
|
// pass
|
|
|
|
//# timestamp followed by byte
|
|
// try:
|
|
// data = struct.unpack("<IB", self.extradata)
|
|
// extrabyte = data[1]
|
|
// ts = datetime.datetime(2000, 1, 1) + datetime.timedelta(seconds=data[0])
|
|
// ret += ["Timestamp: {}, Byte: {}".format(ts, extrabyte)]
|
|
// except:
|
|
// pass
|
|
|
|
//# just timestamp
|
|
// try:
|
|
// data = struct.unpack("<I", self.extradata)
|
|
// ts = datetime.datetime(2000, 1, 1) + datetime.timedelta(seconds=data[0])
|
|
// ret += ["Timestamp: {}".format(ts)]
|
|
// except:
|
|
// pass
|
|
|
|
//# uint32_t
|
|
// try:
|
|
// data = struct.unpack("<I", self.extradata)
|
|
// ret += ["uint32_t: {}".format(data[0])]
|
|
// except:
|
|
// pass
|
|
|
|
//# uint16_t
|
|
// try:
|
|
// data = struct.unpack("<H", self.extradata)
|
|
// ret += ["uint16_t: {}".format(data[0])]
|
|
// except:
|
|
// pass
|
|
|
|
//# uint8_t
|
|
// try:
|
|
// data = struct.unpack("<B", self.extradata)
|
|
// ret += ["uint8_t: {}".format(data[0])]
|
|
// except:
|
|
// pass
|
|
|
|
// return "\nor\n".join(ret)
|
|
|
|
|
|
// def __repr__(self):
|
|
// text = "File: {} ({})\n".format(self.filename, self.filenametime)
|
|
// text += "Severity: {}\n".format(self.log_type_name())
|
|
// text += "Status: {}\n".format(self.status_lookup())
|
|
// text += "Count: {}\n".format(self.count)
|
|
// text += "Extra data: "
|
|
// text += " ".join(["{:02X}".format(x) for x in self.extradata])
|
|
// text += "\n"
|
|
// guess = self.guess_extra_data()
|
|
// if guess:
|
|
// text += "Extra data may be:\n{}\n".format(guess)
|
|
// return text
|
|
|
|
|
|
//def get_filenames(optical, drive):
|
|
//# open the index file
|
|
// handle = optical.fopen("{}\\logindex".format(drive), "r")
|
|
|
|
// namelist = list()
|
|
// while not optical.feof(handle):
|
|
//# read a filename entry
|
|
// numread, name = optical.fread(4, 1, handle)
|
|
// if numread != 1:
|
|
//# we're not at the end of the file but we don't have a full filename
|
|
// break
|
|
//# convert the name bytes to a number
|
|
// name = struct.unpack("<I", name)[0]
|
|
//# and now convert the number to a string
|
|
// name = "{:08X}".format(name)
|
|
//# add the name to the list
|
|
// namelist.append(name)
|
|
|
|
// optical.fclose(handle)
|
|
// return namelist
|
|
|
|
//def read_file(optical, drive, file):
|
|
// alldata = bytearray()
|
|
|
|
//# open the file
|
|
// handle = optical.fopen("{}\\{}".format(drive, file), "r")
|
|
|
|
// if handle == 0:
|
|
// print("Couldn't open {}, it could be in use by Logger".format(file))
|
|
// else:
|
|
//# work out how big the file is
|
|
// optical.fseek(handle, 0, 2)
|
|
// numbytes = optical.ftell(handle)
|
|
// optical.fseek(handle, 0, 0)
|
|
|
|
//# read all the data
|
|
// bytesread, data = optical.fread(1, numbytes, handle)
|
|
// optical.fclose(handle)
|
|
// print("Read {} bytes from {}".format(bytesread, file))
|
|
|
|
//# stick it in a big structure
|
|
// alldata += bytearray(data)
|
|
|
|
// return alldata
|
|
|
|
//if __name__ == '__main__':
|
|
// import logging
|
|
// import argparse
|
|
|
|
// parser = argparse.ArgumentParser(description="Read the log entries from a Genesis"
|
|
// " 'optical' port")
|
|
// parser.add_argument('serialport', help='what serial port to use')
|
|
// parser.add_argument('--drive', default=1, help='meter drive to read')
|
|
// parser.add_argument('--irda', action='store_true', default=False)
|
|
|
|
// args = parser.parse_args()
|
|
|
|
//# Open the serial port
|
|
// o = oa.BreezeOptical(args.serialport, irda=args.irda)
|
|
|
|
//# log into the meter
|
|
// print("Logging out - to get a stable start situation")
|
|
//# logging.basicConfig(level=logging.DEBUG, filename= '18708048.log', filemode='w')
|
|
// o.login(0)
|
|
|
|
//# print the serial number
|
|
// print("PCB Serial Number: {}".format(o.CONFIGEXCHANGE_PCBSerialNumber))
|
|
|
|
//# log into the meter
|
|
// print("Logging in")
|
|
// o.login(8)
|
|
|
|
//# print the meter time
|
|
// print("Meter time: {}".format(o.SYSTEM_CalendarSeconds))
|
|
|