using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace SportO.ScaleReader.Services
{
class ScaleReader : Form
{
static bool debug = false;
// Serial Port
static SerialPort scaleSerialPort;
static string weight = "0";
static bool formatAsWholeNumber = false;
static string _com = "COM3";
static int _baud = 9600;
static int _dataBits = 7;
static StopBits _stopBits = StopBits.One;
static Parity _parity = Parity.Even;
// Keyboard listener
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private static LowLevelKeyboardProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
// Remove the close button
private const int MF_BYCOMMAND = 0x00000000;
public const int SC_CLOSE = 0xF060;
[DllImport("user32.dll")]
public static extern int DeleteMenu(IntPtr hMenu, int nPosition, int wFlags);
[DllImport("user32.dll")]
private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[DllImport("kernel32.dll", ExactSpelling = true)]
private static extern IntPtr GetConsoleWindow();
static void Main(string[] args)
{
Console.Title = "SportO_Scale_Reader";
setConsoleWindowVisibility(false);
DeleteMenu(GetSystemMenu(GetConsoleWindow(), false), SC_CLOSE, MF_BYCOMMAND);
Console.TreatControlCAsInput = true;
setupSerialPort();
_hookID = SetHook(_proc);
Application.Run();
UnhookWindowsHookEx(_hookID);
}
#region SerialPort_and_Weight
/// <summary>
/// A DataRecieved Event that handles the incoming serial data result
/// from a weight query. Only collects the line with the weight and
/// discards anything else.
/// </summary>
// Event handler for data received on serial port line
static void scale_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string buffer = "";
try
{
buffer += scaleSerialPort.ReadLine();
if (!string.IsNullOrWhiteSpace(buffer.Trim()) && buffer.Contains('l'))
{
weight = buffer;
if (debug) Console.WriteLine("Scale Message: " + weight);
writeWeightToKeyboard(formatAsWholeNumber);
scaleSerialPort.Close();
}
}
catch (TimeoutException ex)
{
buffer = "Re-Try";
if (debug) Console.WriteLine(ex);
}
}
static void setupDataReceived(string com, int baud, int dataBits, StopBits stopBits, Parity parity, string sparity)
{
_com = com;
_baud = baud;
_dataBits = dataBits;
_stopBits = stopBits;
_parity = parity;
Settings.Default.com = _com;
Settings.Default.baud = _baud;
Settings.Default.dataBits = _dataBits;
Settings.Default.parity = sparity;
Settings.Default.Save();
setupSerialPort();
}
// Write to scale on serial port requeesting current weight reading
private static void requestWeight()
{
resetSerialPort();
openSerialPort();
scaleSerialPort.Write("W\r");
}
// Setup, open and reset serial port
private static void setupSerialPort()
{
_com = Settings.Default.com;
_baud = Settings.Default.baud;
_dataBits = Settings.Default.dataBits;
if (Settings.Default.parity == "odd")
_parity = Parity.Odd;
else if (Settings.Default.parity == "none")
_parity = Parity.None;
scaleSerialPort = new SerialPort();
scaleSerialPort.PortName = _com;
scaleSerialPort.Parity = _parity;
scaleSerialPort.StopBits = _stopBits;
scaleSerialPort.DataBits = _dataBits;
scaleSerialPort.BaudRate = _baud;
scaleSerialPort.Handshake = Handshake.None;
scaleSerialPort.ReadTimeout = 200;
scaleSerialPort.WriteTimeout = 200;
scaleSerialPort.DataReceived += scale_DataReceived;
if (debug) Console.WriteLine("Setup serial port.");
}
private static bool openSerialPort()
{
bool open = false;
if (scaleSerialPort.IsOpen)
scaleSerialPort.Close();
try
{
scaleSerialPort.Open();
open = true;
}
catch (Exception e)
{
if (debug) Console.WriteLine(e);
Console.WriteLine("Could not connect to scale.");
SendKeys.SendWait("^a");
SendKeys.SendWait("Error-C23");
}
return open;
}
private static void resetSerialPort()
{
try
{
if (scaleSerialPort.IsOpen)
scaleSerialPort.Close();
}
catch(Exception myexp)
{
if (debug) Console.WriteLine(myexp);
}
scaleSerialPort.Dispose();
setupSerialPort();
if (debug) Console.WriteLine("Reset serial port.");
}
// Weight methods
private static string formatWeight(bool wholeNumber)
{
string roundedWeight = "";
try
{
double doubleWeight = 0;
Double.TryParse(weight.Replace(Environment.NewLine, "-").Trim().Split('l')[0], out doubleWeight);
if (wholeNumber)
doubleWeight = Math.Ceiling(doubleWeight);
else
doubleWeight = Math.Round((Math.Ceiling(doubleWeight * 10.0) / 10), 1);
roundedWeight += doubleWeight.ToString();
}
catch (IndexOutOfRangeException exp) { if (debug) Console.WriteLine(exp); }
catch (Exception expp) { if (debug) Console.WriteLine(expp); }
if (debug) Console.WriteLine("Rounded: " + roundedWeight);
return roundedWeight;
}
private static void writeWeightToKeyboard(bool wholeNumber)
{
if (debug) Console.WriteLine("After Wait Loop: " + weight);
SendKeys.SendWait("^a");
SendKeys.SendWait(formatWeight(wholeNumber));
}
#endregion
#region Keyboard_Listener
/// <summary>
/// Keyboard listener checks for F11 and F12 Key down events
/// If found, then scale is queried for current weight reading,
/// weight is rounded up to nearest 1/10th (F11) or the nearest whole number (F12)
/// and the result is sent across the keyboard after a select all command.
/// Otherwise, nothing happens.
/// </summary>
private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
}
}
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
Keys pressedKey = (Keys)Marshal.ReadInt32(lParam);
if (pressedKey == Keys.F11 || pressedKey == Keys.F12)
{
try
{
if (debug) Console.WriteLine("F11 or F12 Pressed!");
formatAsWholeNumber = pressedKey == Keys.F11 ? false : true;
requestWeight();
}
catch (Exception myexp)
{
if (debug) Console.WriteLine(myexp);
}
return (System.IntPtr)1;
}
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
#endregion
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName,string lpWindowName);
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
}
}