Skip to content

Instantly share code, notes, and snippets.

View developerfromjokela's full-sized avatar
🪒
tinkering

DFJ developerfromjokela

🪒
tinkering
View GitHub Profile
@developerfromjokela
developerfromjokela / DRSTR.md
Created September 22, 2026 21:40
Clarion Maps structure + decompressor of CMP files

Directory Structure File

TOP SECTION

0x28 items (top level dirs)

2F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 01 00 0F 00 00 00 00 00 00 00 00 00 00 00 78 05 00 00

Top Level Dir Record (starts from offset 0)

@developerfromjokela
developerfromjokela / main.py
Last active April 12, 2026 15:03
Binary protocol diff tool, helps analyzing unknown binary protocols based on multiple capture datas
import tkinter as tk
from tkinter import ttk, filedialog
import os
import colorsys
FILE_HUES = [0.60, 0.05, 0.35, 0.15, 0.75, 0.50, 0.90, 0.28]
FONT_FAMILY = "Courier New"
FONT_SIZE = 11
LABEL_WIDTH = 180
@developerfromjokela
developerfromjokela / index.php
Created October 17, 2025 20:03
Calendar app for OpenCARWINGS via datachannel
<?php
// Handle POST request with timezone data
$postData = null;
$timezoneOffset = 3; // Default EEST offset in hours
$userTimezone = 'Europe/Helsinki'; // Default timezone
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$postJson = file_get_contents('php://input');
$postData = json_decode($postJson, true);
@developerfromjokela
developerfromjokela / index.php
Last active October 17, 2025 19:28
Nordpool market price for OpenCARWINGS
<?php
// Handle POST request with timezone data
$postData = null;
$timezoneOffset = 3; // Default EEST offset in hours
$userTimezone = 'Europe/Helsinki'; // Default timezone
$zone = "FI";
$vat = 1.255;
if (isset($_GET['z'])) {
@developerfromjokela
developerfromjokela / libbs.cpp
Created September 16, 2025 20:32
Full utility in C++ for converting Xanavi/Clarion/NissanLeaf map Mesh IDs (including encoded ones)
#include "libbs.h"
#include <stdint.h>
#include <cstdint>
#include <cstdio>
#include <sys/types.h>
/*
* "MonsterID" is encoded Mesh ID composed for charging station updates, so far used only for CarWings CP updates
*/
int32_t UnpackMonsterIDIntoMeshID(int32_t monsterId)
@developerfromjokela
developerfromjokela / nksum.py
Created May 8, 2025 11:16
Calculate NK update file SUM, Xanavi/Clarion 72xx
import argparse
def compute_checksum_and_verify(data: bytes) -> bool:
data_array = bytearray(data)
checksum_offset = 0x30
# Read and temporarily clear the stored checksum for region 0
original_checksum = int.from_bytes(data_array[checksum_offset:checksum_offset+2], byteorder='little')
data_array[checksum_offset:checksum_offset+2] = [0, 0]
# Calculate checksum by summing all bytes
@developerfromjokela
developerfromjokela / configuration.yaml
Created April 30, 2025 13:21
OpenCARWINGS Home Assistant template, add this to yoru configuration
template:
- binary_sensor:
- name: "EV Charging"
unique_id: ev_charging
device_class: battery_charging
state: >
{{ state_attr('sensor.ev_raw_data', 'ev_info').charging }}
- name: "EV Quick Charging"
unique_id: ev_qc_charging
device_class: battery_charging
@developerfromjokela
developerfromjokela / main.py
Created February 16, 2025 20:49
KWP extract
import sys
import struct
def extract_firmware(input_file, output_file):
DEFAULT_OUTPUT_SIZE = 300 * 1024 * 1024 # 1MB
total_bytes_extracted = 0
try:
with open(input_file, "rb") as infile:
@developerfromjokela
developerfromjokela / laskuri.py
Last active July 25, 2023 17:50
Wilma opintopiste laskuri
import requests
# Wilma2SID= cookie value here
SESSION = ""
# Your Wilma Base URL
BASEURL = "https://example.inschool.fi/!0249962/"
# Schedule ID as ENV if you know already, otherwise select using CLI
SCHEDULE = os.environ.get("SCHEDULE", '')
@developerfromjokela
developerfromjokela / parse.js
Created June 27, 2021 23:15
Parse Wilma Course Tray schedule generator
const {parseData} = require('./utils');
let jsonConf = "{\"others\":[{\"data\":\"1,585,75\",\"text\":\"vENA11.1, tukikurssi\"},{\"data\":\"1,670,105\",\"text\":\"vSAA05.1\"},{\"data\":\"1,785,75\",\"text\":\"vMAA05.3\"},{\"data\":\"1,870,75\",\"text\":\"vYH02.3\"},{\"data\":\"2,585,75\",\"text\":\"vSAA05.1\"},{\"data\":\"2,670,105\",\"text\":\"vÄI04.2\"},{\"data\":\"2,870,75\",\"text\":\"vOP06.3, HYK20C, klo 13.05-13.20\"},{\"data\":\"3,495,75\",\"text\":\"vYH02.3\"},{\"data\":\"3,585,75\",\"text\":\"vÄI04.2\"},{\"data\":\"3,670,105\",\"text\":\"vENA11.1, tukikurssi\"},{\"data\":\"4,585,75\",\"text\":\"vMAA05.3\"},{\"data\":\"4,670,105\",\"text\":\"vSAA05.1\"},{\"data\":\"4,785,75\",\"text\":\"vYH02.3\"},{\"data\":\"5,585,75\",\"text\":\"vENA11.1, tukikurssi\"},{\"data\":\"5,670,105\",\"text\":\"vMAA05.3\"},{\"data\":\"5,785,75\",\"text\":\"vÄI04.2\"}],\"checksum\":\"CE2089E\"}";
jsonConf = JSON.parse(jsonConf);
let multiplier = 1;
let globalItems = [];
jsonConf.others.forEach(item => {
let items = pars