Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plugin for Shadin protocol #173

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions doc/plugins/shadin.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
====================
Shadin Plugin
====================

Implements Shadin protocol. Currently only decodes fuel related messages supported by FC-10 fuel computer


Example data
------------
ZA---
ZB---
ZC---
ZD ----
ZE ----
ZF --
ZG --
ZH---
ZI---
ZJ --
ZK ---
ZL---
GM0000
GN00000
GO0000
GP00000
GQ000
GR051

Protocol description
--------------------
SHADIN “G” FORMAT
<STX> GA012<CR><LF> GB345<CR><LF> GC678<CR><LF> GD<+/->9012<CR><LF> GE<+/->3456<CR><LF> GF<+/->78<CR><LF> GG<+/->90<CR><LF> GH123<CR><LF> GI456<CR><LF> GJ<+/->78<CR><LF> GK<+/->901<CR><LF> GL234<CR><LF> GM5678<CR><LF>† GN90123<CR><LF>† GO4567<CR><LF> GP89012<CR><LF> GQ001<CR><LF>
GR6789.0<CR><LF>† Ga<+/->1234<CR><LF> Gb56.78<CR><LF> G*901<CR><LF> <ETX>
"GA" (ASCII characters); "012" represents indicated Air Speed (knots)
"GB" (ASCII characters); "345" represents true Air Speed (knots)
"GC" (ASCII characters); "678" represents Mach Speed (thousandths)
"GD" (ASCII characters); sign; "9012" represents pressure altitude (tens of feet) "GE" (ASCII characters); sign; "3456" represents density altitude (tens of feet) "GF" (ASCII characters); sign; "78" represents outside air temperature (Celsius) "GG" (ASCII characters); sign; "90" represents true air temperature (Celsius) "GH" (ASCII characters); "123" represents wind direction (degrees from north) "GI" (ASCII characters); "456" represents wind speed (knots)
"GJ" (ASCII characters); sign; "78" represents rate of turn (degrees per second)
"GK" (ASCII characters); sign; "901" represents vertical speed (tens of ft/minute)
"GL" (ASCII characters); "234" represents heading (degrees from north)
"GM" (ASCII characters); "5678" represents fuel flow, right (Twin only) (tenths gallons/hour) "GN" (ASCII characters); "90123" represents fuel used, right (Twin only) (tenths gallons) "GO" (ASCII characters); "4567" represents fuel flow, left (or Single) (tenths gallons/hour) "GP" (ASCII characters); "89012" represents fuel used, left (or Single) (tenths gallons)
"GQ" (ASCII characters); "001" represents error log/reason indicator (001 = temp. sensor error, 000 = no errors)
"GR" (ASCII characters); "6789.0" represents fuel remaining (gallons)
"Ga" (ASCII characters); sign; "12.34" represents barometric corrected altitude (tens of feet) "Gb" (ASCII characters); "56.78" represents current barometric pressure setting (inches Hg) "G*" (ASCII characters); "901" represents checksum
Where:
<STX> start-transmit character (0x02)
<CR> carriage-return character (0x0d)
<LF> line-feed character (0x0a)
<+/-> sign indicator (0x2b["+"] or 0x2d["-"]) <ETX> end-transmit character (0x03)
5 changes: 5 additions & 0 deletions fixgw/config/connections/shadin.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
shadin:
load: SHADIN
module: fixgw.plugins.shadin
port: /dev/ttyACM0
baud: 9600
1 change: 1 addition & 0 deletions fixgw/config/default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ connections:
- IFLY_CONFIG
- MEGASQUIRT_CONFIG
- MGL_CONFIG
- SHADIN_CONFIG
- DEMO_CONFIG

# Logging configuration - See Python logging.config module documenation
Expand Down
2 changes: 2 additions & 0 deletions fixgw/config/preferences.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ includes:
IFLY_CONFIG: connections/ifly.yaml
MEGASQUIRT_CONFIG: connections/megasquirt.yaml
MGL_CONFIG: connections/mgl.yaml
SHADIN_CONFIG: connections/shadin.yaml
DEMO_CONFIG: connections/demo.yaml
# This section is used to turn things on or off
enabled:
Expand Down Expand Up @@ -60,5 +61,6 @@ enabled:
IFLY: false
MEGASQUIRT: false
MGL: false
SHADIN: false
DEMO: true

116 changes: 116 additions & 0 deletions fixgw/plugins/shadin/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#!/usr/bin/env python

# Copyright (c) 2024 Janne Mäntyharju
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

# Plugin for Shadin protocol. Currently only fuel related items are supported
# Fdatasystems FC-10 fuel computer was used for testing

import threading
from collections import OrderedDict

import serial
import fixgw.plugin as plugin


class MainThread(threading.Thread):
def __init__(self, parent):
super(MainThread, self).__init__()
self.getout = False # indicator for when to stop
self.parent = parent # parent plugin object
self.log = parent.log # simplifies logging
self._c = None

def run(self):
try:
self._c = serial.Serial(self.parent.config['port'],
self.parent.config['baud'],
timeout=0.5,)
except serial.serialutil.SerialException:
self.parent.log.error(f"Could not open port: {self.parent.config['port']}")
return

while not self.getout:
try:
self._parse(self._c.read_until())
except serial.SerialException:
self.parent.log.error("Serial port error")

def stop(self):
self.getout = True

def _parse(self, message):
if not len(message):
return

message = message.decode('ASCII')

if not message.endswith('\n'):
self.parent.log.debug("Incomplete message received")
return

index = message.find('Z')

if index != -1:
message = message[index:]
else:
self.parent.log.debug("Beginning of message was not found")

if message.startswith("ZM"): # Fuel flow right
if "FUELF2" not in self.parent.db_list():
# Second engine not in config
return

try:
fuel_flow = int(message[2:])
except ValueError:
self.parent.log.error(f"Bad data received: {message}")
return
self.parent.db_write("FUELF2", fuel_flow / 0.1)
elif message.startswith("ZO"): # Fuel flow left
try:
fuel_flow = int(message[2:])
except ValueError:
self.parent.log.error(f"Bad data received: {message}")
return
self.parent.db_write("FUELF1", fuel_flow / 0.1)
elif message.startswith("ZR"): # Fuel remaining
try:
fuel_remaining = float(message[2:])
except ValueError:
self.parent.log.error(f"Bad data received: {message}")
return
self.parent.db_write("FUELQT", fuel_remaining)


class Plugin(plugin.PluginBase):
def __init__(self, name, config):
super(Plugin, self).__init__(name, config)
self.thread = MainThread(self)
self.status = OrderedDict()

def run(self):
self.thread.start()

def stop(self):
self.thread.stop()
if self.thread.is_alive():
self.thread.join(1.0)
if self.thread.is_alive():
raise plugin.PluginFail

def get_status(self):
return self.status