-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* cleanup from old branch * added little structs * added big structs * added overarching objects * reworked mapping to use tags * added new PoC * updated module paths to make mypy slightly happier
- Loading branch information
Showing
12 changed files
with
264 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,18 @@ | ||
build/ | ||
dist/ | ||
__pycache__/ | ||
logs/ | ||
# editor things | ||
.idea/ | ||
output.csv | ||
.zed/ | ||
.vscode/ | ||
|
||
# Added by cargo | ||
# misc things | ||
.DS_Store | ||
.gitignore | ||
|
||
# python things | ||
pyrightconfig.json | ||
__pycache__/ | ||
|
||
# Added by cargo (rust things) | ||
/target | ||
build/ | ||
dist/ | ||
logs/ |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
from structs.CANField import CANField | ||
from structs.CANMsg import CANMsg | ||
from structs.Decoding import Decoding | ||
|
||
from typing import Optional | ||
|
||
class RustSynth: | ||
''' | ||
A class to synthesize Rust from a given CANMsg spec. | ||
''' | ||
|
||
inst_hashmap: str = " let mut result = HashMap::new();" | ||
closing: str = " result\n}" | ||
|
||
def synthesize(self, msg: CANMsg) -> str: | ||
signature: str = self.signature(msg.desc) | ||
generated_lines: list[str] = [] | ||
for field in msg.fields: | ||
generated_lines.append(self.finalize_line(field.id, f"({self.parse_decoders(field)}){self.correcting_factor(field)}")) | ||
total_list: list[str] = [signature, self.inst_hashmap] + generated_lines + [self.closing] | ||
return "\n".join(total_list) | ||
|
||
def signature(self, to_decode: str) -> str: | ||
return f"pub fn decode_{to_decode.replace(' ', '_')}(data: &[u8]) -> HashMap<u8, f32> {{" | ||
|
||
def finalize_line(self, id: int, val: str) -> str: | ||
return f" result.insert({id}, {val});" | ||
|
||
def parse_decoders(self, field: CANField) -> str: | ||
if isinstance(field.decodings, type(None)): | ||
return f"data[{field.index}] as f32" | ||
else: | ||
base: str = f"&data[{field.index}..{field.index + field.size}]" | ||
for decoder in field.decodings: | ||
base = f"pd::{decoder.repr}({base}, {decoder.bits}) as {decoder.final_type}" | ||
return base | ||
|
||
def correcting_factor(self, field:CANField) -> str: | ||
cf: str = "" | ||
if field.correcting_factor: | ||
cf = f" {field.correcting_factor.op} {field.correcting_factor.const}" | ||
return cf |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
from io import TextIOWrapper | ||
from ruamel.yaml import YAML, Any | ||
|
||
from structs.CANMsg import CANMsg | ||
from structs.CANField import CANField | ||
from structs.CorrectingFactor import CorrectingFactor | ||
import structs.Decoding | ||
|
||
class YAMLParser: | ||
''' | ||
A class to parse a given YAML string or file. Most of the heavy lifting | ||
is done by the internals of ruamel.yaml. | ||
''' | ||
|
||
def __init__(self): | ||
self.yaml = YAML() | ||
self.yaml.register_class(CANMsg) | ||
self.yaml.register_class(CANField) | ||
self.yaml.register_class(CorrectingFactor) | ||
for decoding in structs.Decoding.Decoding.__subclasses__(): | ||
self.yaml.register_class(decoding) | ||
|
||
|
||
def parse(self, file: Any) -> CANMsg: | ||
return self.yaml.load(file) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
!CANMsg | ||
id: 1 | ||
desc: "accumulator status" | ||
fields: | ||
- !CANField | ||
id: 1 | ||
name: Pack Inst Voltage | ||
units: "V" | ||
size: 2 | ||
decodings: | ||
- !BigEndian | ||
bits: 8 | ||
final_type: "f32" | ||
correcting_factor: | ||
!CorrectingFactor | ||
const: 10.0 | ||
op: "/" | ||
- !CANField | ||
id: 2 | ||
name: "Pack Current" | ||
units: "A" | ||
size: 2 | ||
decodings: | ||
- !BigEndian | ||
bits: 8 | ||
final_type: "u32" | ||
- !TwosComplement | ||
bits: 16 | ||
final_type: "f32" | ||
correcting_factor: | ||
!CorrectingFactor | ||
const: 10.0 | ||
op: "/" | ||
- !CANField | ||
id: 3 | ||
name: "Pack Amp-hours" | ||
units: "Ah" | ||
size: 2 | ||
decodings: | ||
- !BigEndian | ||
bits: 8 | ||
final_type: "f32" | ||
- !CANField | ||
id: 4 | ||
name: "Pack SOC" | ||
units: "%" | ||
size: 1 | ||
final_type: "f32" | ||
- !CANField | ||
id: 5 | ||
name: "Pack Health" | ||
units: "%" | ||
size: 1 | ||
final_type: "f32" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
from ruamel.yaml import YAML, Any | ||
from functools import reduce | ||
|
||
|
||
yaml: YAML = YAML(typ="safe") | ||
|
||
out_string: str = "" | ||
data: dict[str, Any] = yaml.load(open("mapping.yaml")) | ||
print(data) | ||
print(type(data)) | ||
|
||
function_name: str = "decode" + "_" + "_".join(data['string'].split(" ")) | ||
args: str = "(data: &[u8])" | ||
returnVal: str= " -> HashMap<u8, f32>" | ||
|
||
signature: str = "pub fn " + function_name + args + returnVal + " {" | ||
instantiate_hash_map: str = " let mut result = HashMap::new();" | ||
conclusion: str = " result\n}" | ||
|
||
decodings: list[str] = [] | ||
accumulated_size: int = 0 | ||
for field in data["fields"]: # result.insert(1, (pd::big_endian(&data[0..2], 8) as f32) / 10.0); | ||
field: dict | ||
decoded: str | ||
id = field["field_id"] | ||
if field["size"] > 1: # we need to do some decoding, then | ||
to_decode: str = f"&data[{accumulated_size}..{accumulated_size+field['size']}]" | ||
_cf: str = field.get("correcting_factor", "") | ||
correcting_factor: str = f"{' ' + ('/' if '/' in _cf else '*') + ' ' if 'correcting_factor' in field.keys() else ''}{_cf.split('/')[-1]}" | ||
for decodingsetup in field["decoding"]: | ||
decodingsetup: dict[str, dict[str, str]] = {k: reduce(lambda x,y: x|y, v, {}) for k,v in decodingsetup.items()} | ||
for decoder, params in decodingsetup.items(): | ||
match decoder: | ||
case "big_endian": | ||
to_decode = f"pd::big_endian({to_decode}, {params['bits']}) as {params['final_type']}" | ||
case "twos_complement": | ||
to_decode = f"pd::twos_comp({to_decode}, {params['bits']}) as {params['final_type']}" | ||
decoded = f"{id}, {to_decode}{correcting_factor}" | ||
else: # no decoding required! | ||
decoded = f"{id}, data[{accumulated_size}] as {field['final_type']}" | ||
|
||
decodings.append(decoded) | ||
accumulated_size += field["size"] | ||
|
||
formatted_decodings = [f" result.insert({i});" for i in decodings] | ||
|
||
finals: list[str] = [signature, instantiate_hash_map] + formatted_decodings + [conclusion] | ||
print("\n".join(finals)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
from __future__ import annotations | ||
from .CorrectingFactor import CorrectingFactor | ||
from .Decoding import * | ||
from ruamel.yaml import Optional | ||
from dataclasses import dataclass | ||
|
||
@dataclass | ||
class CANField: | ||
''' | ||
Represents a field in a CAN message. Has an id, a name, units, a size, | ||
and an optional CorrectingFactor and Decodings. Also knows its own | ||
index within its parent CANMsg, which is assigned at load from YAML. | ||
''' | ||
id: int | ||
name: str | ||
units: str | ||
size: int | ||
index: int = -1 | ||
correcting_factor: Optional[CorrectingFactor] = None | ||
decodings: Optional[list[Decoding]] = None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
from __future__ import annotations | ||
from ruamel.yaml import Optional, MappingNode | ||
from structs.CorrectingFactor import CorrectingFactor | ||
from .CANField import CANField | ||
from dataclasses import dataclass | ||
|
||
@dataclass | ||
class CANMsg: | ||
''' | ||
Represents a CAN message. Has an id, a description, and a number of individual fields. | ||
''' | ||
id: int | ||
desc: str | ||
fields: list[CANField] | ||
|
||
def __post_init__(self) -> None: | ||
idx: int = 0 | ||
for field in self.fields: | ||
field.index = idx | ||
idx += field.size | ||
|
||
|
||
def __setstate__(self, state): | ||
self.__init__(**state) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
from dataclasses import dataclass | ||
|
||
@dataclass | ||
class CorrectingFactor: | ||
''' | ||
Represents a correcting factor to be applied to data after decoding. | ||
''' | ||
const: float | ||
op: str |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
from dataclasses import dataclass | ||
|
||
@dataclass | ||
class Decoding: | ||
''' | ||
This is an abstract class (well, what passes for one in Python) | ||
that represents a decoding to be applied to a slice of data. | ||
''' | ||
bits: int | ||
final_type: str | ||
repr: str = "*"*42 | ||
|
||
@dataclass | ||
class BigEndian(Decoding): | ||
repr: str = "big_endian" | ||
|
||
@dataclass | ||
class LittleEndian(Decoding): | ||
repr: str = "little_endian" | ||
|
||
@dataclass | ||
class TwosComplement(Decoding): | ||
repr: str = "twos_comp" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
from YAMLParser import YAMLParser | ||
from RustSynth import RustSynth | ||
|
||
print(RustSynth().synthesize(YAMLParser().parse(open("mapping.yaml", "r")))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters