### Start Tachoparser gRPC Server Source: https://github.com/traconiq/tachoparser/blob/main/README.md Run the 'dddserver' executable in the root directory to start the gRPC server on the default port 50055. ```bash ./dddserver ``` -------------------------------- ### Build Tachoparser Executables Source: https://context7.com/traconiq/tachoparser/llms.txt This section provides commands to build all production binaries or individual executables for the Tachoparser project. It also includes instructions for running unit tests and installing the main parser to the system path. ```bash # Build all production binaries at once ./build-binaries-prod.sh # Or build individually go mod vendor cd cmd/dddparser && go build . # Full parser cd cmd/dddsimple && go build . # Simplified parser cd cmd/dddserver && go build . # gRPC server cd cmd/dddclient && go build . # gRPC client cd cmd/dddui && go build . # Desktop GUI (requires display) # Run unit tests (decoder type tests) cd pkg/decoder && go test -v # Example output: # --- PASS: TestDecodeInt16 (0.00s) # --- PASS: TestDecodeUint32 (0.00s) # PASS # Install dddparser to system path sudo cp cmd/dddparser/dddparser /usr/local/bin/ ``` -------------------------------- ### Start Tachoparser gRPC Server on Custom Port Source: https://github.com/traconiq/tachoparser/blob/main/README.md Use the '-listen' option with 'dddserver' to specify a different port for the gRPC server to listen on. ```bash ./dddserver -listen :50056 ``` -------------------------------- ### Install Tachoparser dddparser Executable Source: https://github.com/traconiq/tachoparser/blob/main/README.md Copy the compiled 'dddparser' executable to a directory in your system's PATH for easy access. ```bash sudo cp cmd/dddparser/dddparser /usr/local/bin ``` -------------------------------- ### Start dddserver gRPC Parsing Server Source: https://context7.com/traconiq/tachoparser/llms.txt Launches a gRPC server for remote tachograph data parsing. Supports custom ports, statsd metrics, and Consul service discovery. ```bash # Start server on default port 50055 ./dddserver ``` ```bash # Start on a custom port ./dddserver -listen :50056 ``` ```bash # With statsd metrics reporting ./dddserver -listen :50055 -statsd localhost:8125 ``` ```bash # With Consul service registration (env vars) CONSUL_ADDR=consul.example.com:8500 \ CONSUL_SERVICE_NAME=tachoparser \ CONSUL_DATACENTER=dc1 \ ./dddserver -listen :50055 ``` ```bash # Docker deployment (only dddserver is included in the Docker image) docker build -t tachoparser . docker run -p 50055:50055 tachoparser ``` -------------------------------- ### dddserver - gRPC parsing server Source: https://context7.com/traconiq/tachoparser/llms.txt Starts a gRPC server that exposes two RPC methods (ParseVu, ParseCard) for remote tachograph data parsing. Supports Consul service discovery and statsd metrics. ```APIDOC ## dddserver ### Description Starts a gRPC server that exposes two RPC methods (`ParseVu`, `ParseCard`) for remote tachograph data parsing. Supports Consul service discovery and statsd metrics. ### Usage * **Start server on default port 50055:** ```bash ./dddserver ``` * **Start on a custom port:** ```bash ./dddserver -listen :50056 ``` * **With statsd metrics reporting:** ```bash ./dddserver -listen :50055 -statsd localhost:8125 ``` * **With Consul service registration (env vars):** ```bash CONSUL_ADDR=consul.example.com:8500 \ CONSUL_SERVICE_NAME=tachoparser \ CONSUL_DATACENTER=dc1 \ ./dddserver -listen :50055 ``` * **Docker deployment (only dddserver is included in the Docker image):** ```bash docker build -t tachoparser . docker run -p 50055:50055 tachoparser ``` ``` -------------------------------- ### dddparser: Parse VU Data from Stdin Source: https://context7.com/traconiq/tachoparser/llms.txt Use the `dddparser` CLI tool to parse VU tachograph data piped to `stdin`. The output is a complete JSON representation sent to `stdout`. Warnings and errors are directed to `stderr`. This example uses `jq` for pretty-printing. ```bash cat tachodata.ddd | ./dddparser -vu | jq . | less ``` -------------------------------- ### Building Executables Source: https://context7.com/traconiq/tachoparser/llms.txt Instructions for building the Tachoparser executables. ```APIDOC ## Building Executables ### Description Instructions for building the various executables provided by the Tachoparser project. ### Commands 1. **Build all production binaries:** ```bash ./build-binaries-prod.sh ``` 2. **Build individual binaries:** ```bash go mod vendor cd cmd/dddparser && go build . # Full parser cd cmd/dddsimple && go build . # Simplified parser cd cmd/dddserver && go build . # gRPC server cd cmd/dddclient && go build . # gRPC client cd cmd/dddui && go build . # Desktop GUI (requires display) ``` 3. **Run unit tests:** ```bash cd pkg/decoder && go test -v ``` 4. **Install `dddparser` to system path:** ```bash sudo cp cmd/dddparser/dddparser /usr/local/bin/ ``` ``` -------------------------------- ### Build Tachoparser Executable Locally Source: https://github.com/traconiq/tachoparser/blob/main/README.md After running 'go mod vendor', navigate to the 'cmd/dddparser' directory (or any other 'cmd' subdirectory) and use 'go build' to compile the executable. ```bash go build . ``` -------------------------------- ### Build Tachoparser Binaries Source: https://github.com/traconiq/tachoparser/blob/main/README.md Execute this script in the root directory to build the production binaries for the Tachoparser project. ```bash ./build-binaries-prod.sh ``` -------------------------------- ### Downloading ERCA Public Key Certificates Source: https://context7.com/traconiq/tachoparser/llms.txt Instructions for downloading and setting up ERCA public key certificates required for signature verification. ```APIDOC ## Downloading ERCA Public Key Certificates ### Description Before signature verification works, the EU root CA and member state certificates must be downloaded and placed in `pks1/` (1st gen) and `pks2/` (2nd gen) directories relative to the executable. ### Commands 1. **Download 1st generation keys:** ```bash cd scripts/pks1 python3 dl_all_pks1.py ``` Keys are saved as `.bin` in `pks1/`. 2. **Download 2nd generation keys:** ```bash cd ../pks2 python3 dl_all_pks2.py ``` Keys are saved as `.bin` in `pks2/`. 3. **Verify keys are loaded:** ```bash ./dddparser -vu < /dev/null 2>&1 ``` Expected output includes `loaded certificates: `. ### Manual Alternative Download certificates from ERCA and rename them to their certificate reference: - 1st gen: https://dtc.jrc.ec.europa.eu/dtc_public_key_certificates_dt.php.html - 2nd gen: https://dtc.jrc.ec.europa.eu/dtc_public_key_certificates_st.php.html ``` -------------------------------- ### Download Public Keys for Tachoparser Source: https://github.com/traconiq/tachoparser/blob/main/README.md Use these bash scripts to download and organize the necessary public keys for data verification. Ensure you run them from the respective 'pks1' and 'pks2' directories. ```bash cd pks1 ./dl_all_pks1.py cd .. cd pks2 ./dl_all_pks2.py cd .. ``` -------------------------------- ### Parse VU Data Remotely using Go gRPC Client Source: https://context7.com/traconiq/tachoparser/llms.txt Demonstrates how to use a Go gRPC client to connect to a `dddserver`, send raw VU data, and process the returned `Vu` protobuf message. Includes accessing specific fields and marshaling to JSON. ```go import ( "context" "fmt" "log" "os" pb "github.com/traconiq/tachoparser/pkg/proto" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "google.golang.org/protobuf/encoding/protojson" ) func parseVuViaGRPC(addr, filePath string) { data, _ := os.ReadFile(filePath) conn, err := grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { log.Fatalf("dial: %v", err) } defer conn.Close() client := pb.NewDDDParserClient(conn) resp, err := client.ParseVu(context.Background(), &pb.ParseVuRequest{Data: data}) if err != nil { log.Fatalf("ParseVu: %v", err) } vu := resp.Vu // Access 1st gen overview fmt.Printf("VIN: %s\n", vu.VuOverview_1.VehicleIdentificationNumber) fmt.Printf("Verified: %v\n", vu.VuOverview_1.Verified) // Access 2nd gen activities for _, act := range vu.VuActivities_2 { fmt.Printf("Activity block verified: %v, records: %d\n", act.Verified, act.VuActivityDailyRecordArray.NoOfRecords) } // Marshal to JSON opts := protojson.MarshalOptions{AllowPartial: true, UseProtoNames: true} out, _ := opts.Marshal(resp.Vu) fmt.Println(string(out)) } ``` -------------------------------- ### Parse Driver Card Data Remotely via gRPC Source: https://context7.com/traconiq/tachoparser/llms.txt This Go function demonstrates how to connect to a gRPC server, send raw driver card binary data, and receive a decoded Card protobuf message. Ensure the gRPC server is running and accessible at the specified address. ```go func parseCardViaGRPC(addr, filePath string) { data, _ := os.ReadFile(filePath) conn, _ := grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials())) defer conn.Close() client := pb.NewDDDParserClient(conn) resp, err := client.ParseCard(context.Background(), &pb.ParseCardRequest{Data: data}) if err != nil { log.Fatalf("ParseCard: %v", err) } card := resp.Card // Driver identity (1st gen section) id1 := card.CardIdentificationAndDriverCardHolderIdentification_1 if id1 != nil { dh := id1.DriverCardHolderIdentification fmt.Printf("Driver: %s %s\n", dh.CardHolderName.HolderFirstNames, dh.CardHolderName.HolderSurname) fmt.Printf("Card number: %s\n", id1.CardIdentification.CardNumber) fmt.Printf("Expires: %d (unix)\n", id1.CardIdentification.CardExpiryDate) } // Daily activity records (1st gen) act1 := card.CardDriverActivity_1 if act1 != nil { fmt.Printf("Activity verified: %v\n", act1.Verified) for _, day := range act1.DecodedActivityDailyRecords { fmt.Printf(" Date=%d Distance=%d changes=%d\n", day.ActivityRecordDate, day.ActivityDayDistance, len(day.ActivityChangeInfo)) } } // Vehicles used (2nd gen) vehicles2 := card.CardVehiclesUsed_2 if vehicles2 != nil { for _, v := range vehicles2.CardVehicleRecords { fmt.Printf("Vehicle: %s first=%d last=%d\n", v.VehicleIdentificationNumber, v.VehicleFirstUse, v.VehicleLastUse) } } } ``` -------------------------------- ### Vendor Go Dependencies for Tachoparser Source: https://github.com/traconiq/tachoparser/blob/main/README.md Run this command to download and manage external dependencies for the Tachoparser project using Go modules. ```bash go mod vendor ``` -------------------------------- ### Run Tachoparser Unit Tests Source: https://github.com/traconiq/tachoparser/blob/main/README.md Execute this command in the root directory to run all available unit tests for decoding various data types. ```bash go test ``` -------------------------------- ### dddparser: Batch Process VU Files Source: https://context7.com/traconiq/tachoparser/llms.txt Use the `dddparser` CLI tool to batch process multiple VU tachograph files listed in a text file. The output JSON files are created with the same base name as the input files, with a `.json` extension, in the same directory. ```bash ls /data/downloads/*.ddd > filelist.txt ./dddparser -vu -input-list filelist.txt ``` -------------------------------- ### Download Public Keys for Signature Verification Source: https://context7.com/traconiq/tachoparser/llms.txt These bash commands download public keys required for signature verification. Ensure you are in the correct directory before running the python scripts. The output indicates the number of keys loaded. ```bash # Download all 1st generation (digital tachograph) public keys cd scripts/pks1 python3 dl_all_pks1.py # Keys are saved as .bin in pks1/ # Download all 2nd generation (smart tachograph) public keys cd ../pks2 python3 dl_all_pks2.py # Keys are saved as .bin in pks2/ # Verify keys are loaded at runtime (logged at startup) ./dddparser -vu < /dev/null 2>&1 # Output: "loaded certificates: 45 38" # (number of 1st gen PKs, number of 2nd gen PKs) # Manual alternative: download from ERCA and rename to certificate reference # https://dtc.jrc.ec.europa.eu/dtc_public_key_certificates_dt.php.html (1st gen) # https://dtc.jrc.ec.europa.eu/dtc_public_key_certificates_st.php.html (2nd gen) ``` -------------------------------- ### dddparser: Parse Driver Card Data to File Source: https://context7.com/traconiq/tachoparser/llms.txt Use the `dddparser` CLI tool to parse driver card data from a specified input file (`-input`) and write the formatted JSON output to a specified file (`-output`). ```bash ./dddparser -card -input drivercard.ddd -output drivercard.json -format ``` -------------------------------- ### Parse Driver Card Data via dddclient gRPC Client Source: https://context7.com/traconiq/tachoparser/llms.txt A reference gRPC client to send raw driver card tachograph data to a `dddserver` and display the JSON response. Requires the server to be running. ```bash # Parse driver card data via gRPC server cat drivercard.ddd | ./dddclient -addr localhost:50055 -card ``` -------------------------------- ### Format dddparser Output with jq Source: https://github.com/traconiq/tachoparser/blob/main/README.md Combine 'dddparser' output with 'jq' for pretty-printing JSON and pipe it to 'less' for easier viewing. ```bash cat tachodata.ddd | dddparser -vu | jq . | less ``` -------------------------------- ### Parse Driver Card Data with dddsimple Source: https://github.com/traconiq/tachoparser/blob/main/README.md Pipe driver card data to 'dddsimple' with the '-card' flag to extract identification numbers and driver names. ```bash cat driverdata.ddd | ./dddsimple -card ``` -------------------------------- ### Parse Driver Card Data with Signature Verification Source: https://context7.com/traconiq/tachoparser/llms.txt Use `decoder.UnmarshalTLV` to decode TLV-encoded driver card binary data into a `decoder.Card` struct. This function also verifies signatures and returns a boolean indicating verification status along with any parsing errors. ```go package main import ( "encoding/json" "fmt" "log" "os" _ "github.com/traconiq/tachoparser/internal/pkg/certificates" "github.com/traconiq/tachoparser/pkg/decoder" ) func main() { data, err := os.ReadFile("drivercard.ddd") if err != nil { log.Fatalf("read file: %v", err) } var card decoder.Card verified, err := decoder.UnmarshalTLV(data, &card) if err != nil { log.Fatalf("parse error: %v", err) } fmt.Printf("Verified: %v\n", verified) // Access driver identification (1st gen fields) id1 := card.CardIdentificationAndDriverCardHolderIdentificationFirstGen fmt.Printf("Driver: %s %s\n", id1.DriverCardHolderIdentification.CardHolderName.HolderFirstNames.String(), id1.DriverCardHolderIdentification.CardHolderName.HolderSurname.String()) fmt.Printf("Card number: %s\n", id1.CardIdentification.CardNumber.String()) // Decode driver activity records dailyRecords := card.CardDriverActivityFirstGen.Decode() for _, day := range dailyRecords { fmt.Printf("Date: %v Distance: %d km\n", day.ActivityRecordDate.Decode(), day.ActivityDayDistance) } out, _ := json.MarshalIndent(card, "", " ") fmt.Println(string(out)) } ``` -------------------------------- ### ParseCard RPC Source: https://context7.com/traconiq/tachoparser/llms.txt Accepts raw driver card binary data and returns a fully decoded Card protobuf message with all data sections and signatures. ```APIDOC ## ParseCard RPC ### Description Accepts raw driver card binary data and returns a fully decoded `Card` protobuf message with all data sections and signatures. ### Method RPC (gRPC) ### Endpoint `ParseCard` ### Request Body - **Data** (bytes) - Required - Raw driver card binary data. ### Response #### Success Response (200) - **Card** (`Card` protobuf message) - The decoded card data. ### Request Example (Go) ```go func parseCardViaGRPC(addr, filePath string) { data, _ := os.ReadFile(filePath) conn, _ := grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials())) defer conn.Close() client := pb.NewDDDParserClient(conn) resp, err := client.ParseCard(context.Background(), &pb.ParseCardRequest{Data: data}) if err != nil { log.Fatalf("ParseCard: %v", err) } card := resp.Card // ... process card data ... } ``` ``` -------------------------------- ### Parse VU Data via dddclient gRPC Client Source: https://context7.com/traconiq/tachoparser/llms.txt A reference gRPC client to send raw VU tachograph data to a `dddserver` and display the JSON response. Requires the server to be running. ```bash # Parse VU data via gRPC server cat tachodata.ddd | ./dddclient -addr localhost:50055 -vu ``` -------------------------------- ### Extract Driver Card Data with dddsimple Source: https://context7.com/traconiq/tachoparser/llms.txt Use `dddsimple -card` to extract driver card numbers and names. This tool is lightweight and suitable for rapid cataloging. ```bash # Extract card number and driver name cat drivercard.ddd | ./dddsimple -card # Output: # {"CardNumber":"123456789012345A","FirstName":"John","LastName":"Doe","CardName":"C_%s_J_Doe_123456789012345A.DDD"} ``` ```bash # Read from a file instead of stdin ./dddsimple -card -input drivercard.ddd ``` -------------------------------- ### ParseVu RPC — Parse Vehicle Unit data remotely Source: https://context7.com/traconiq/tachoparser/llms.txt Accepts raw VU binary data and returns a fully decoded and verified `Vu` protobuf message. ```APIDOC ## gRPC Service API (`DDDParser`) ### `ParseVu` RPC #### Description Accepts raw VU binary data and returns a fully decoded and verified `Vu` protobuf message. #### Request * **Method:** RPC * **Service:** `DDDParser` * **Method Name:** `ParseVu` * **Request Type:** `ParseVuRequest` * `data` (bytes) - Raw VU binary data. #### Response * **Success Response:** `ParseVuResponse` * `vu` (`Vu`) - The decoded and verified `Vu` protobuf message. #### Example (Go) ```go import ( "context" "fmt" "log" "os" pb "github.com/traconiq/tachoparser/pkg/proto" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "google.golang.org/protobuf/encoding/protojson" ) func parseVuViaGRPC(addr, filePath string) { data, _ := os.ReadFile(filePath) conn, err := grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { log.Fatalf("dial: %v", err) } defer conn.Close() client := pb.NewDDDParserClient(conn) resp, err := client.ParseVu(context.Background(), &pb.ParseVuRequest{Data: data}) if err != nil { log.Fatalf("ParseVu: %v", err) } vu := resp.Vu // Access 1st gen overview fmt.Printf("VIN: %s\n", vu.VuOverview_1.VehicleIdentificationNumber) fmt.Printf("Verified: %v\n", vu.VuOverview_1.Verified) // Access 2nd gen activities for _, act := range vu.VuActivities_2 { fmt.Printf("Activity block verified: %v, records: %d\n", act.Verified, act.VuActivityDailyRecordArray.NoOfRecords) } // Marshal to JSON opts := protojson.MarshalOptions{AllowPartial: true, UseProtoNames: true} out, _ := opts.Marshal(resp.Vu) fmt.Println(string(out)) } ``` ``` -------------------------------- ### dddclient - gRPC client Source: https://context7.com/traconiq/tachoparser/llms.txt Reference client that sends raw tachograph data to a `dddserver` over gRPC and prints the JSON response. ```APIDOC ## dddclient ### Description Reference client that sends raw tachograph data to a `dddserver` over gRPC and prints the JSON response. ### Usage * **Parse VU data via gRPC server:** ```bash cat tachodata.ddd | ./dddclient -addr localhost:50055 -vu ``` * **Parse driver card data via gRPC server:** ```bash cat drivercard.ddd | ./dddclient -addr localhost:50055 -card ``` * **Expected output:** Full JSON structure of the Vu or Card protobuf message ```json { "vu_overview_1": { "verified": true, "vehicle_identification_number": "WBA..." }, ... } ``` ``` -------------------------------- ### dddsimple - Quick ID extraction Source: https://context7.com/traconiq/tachoparser/llms.txt A lightweight parser that extracts only identification numbers and driver names without full signature verification. Useful for quickly cataloguing files. ```APIDOC ## dddsimple ### Description Lightweight parser that extracts only identification numbers and driver names without full signature verification. Useful for quickly cataloguing files. ### Usage * **Extract VU identification numbers (VIN + registration plate):** ```bash cat tachodata.ddd | ./dddsimple ``` *Output:* `{"IdentificationNumber":"WBA12345678901234","RegistrationNumber":"AB-CD-1234","VuName":"M_%s_AB-CD-1234_WBA12345678901234.DDD"}` * **Extract card number and driver name:** ```bash cat drivercard.ddd | ./dddsimple -card ``` *Output:* `{"CardNumber":"123456789012345A","FirstName":"John","LastName":"Doe","CardName":"C_%s_J_Doe_123456789012345A.DDD"}` * **Read from a file instead of stdin:** ```bash ./dddsimple -card -input drivercard.ddd ``` ``` -------------------------------- ### Parse Vehicle Unit Data with dddparser Source: https://github.com/traconiq/tachoparser/blob/main/README.md Pipe tachograph data to 'dddparser' with the '-vu' flag to parse vehicle unit data and output JSON to STDOUT. ```bash cat tachodata.ddd | ./dddparser -vu ``` -------------------------------- ### Extract VU Identification Numbers with dddsimple Source: https://context7.com/traconiq/tachoparser/llms.txt Use `dddsimple` to quickly extract Vehicle Unit (VU) identification numbers and driver names from tachograph data files. Reads from stdin by default. ```bash # Extract VU identification numbers (VIN + registration plate) cat tachodata.ddd | ./dddsimple # Output: # {"IdentificationNumber":"WBA12345678901234","RegistrationNumber":"AB-CD-1234","VuName":"M_%s_AB-CD-1234_WBA12345678901234.DDD"} ``` -------------------------------- ### Parse Vehicle Unit (VU) Data with Signature Verification Source: https://context7.com/traconiq/tachoparser/llms.txt Use `decoder.UnmarshalTV` to decode raw VU tachograph binary data into a `decoder.Vu` struct. This function also verifies all embedded digital signatures against loaded ERCA certificates. It returns a boolean indicating verification status and an error if parsing fails. ```go package main import ( "encoding/json" "fmt" "log" "os" _ "github.com/traconiq/tachoparser/internal/pkg/certificates" // loads ERCA PKs at init "github.com/traconiq/tachoparser/pkg/decoder" ) func main() { data, err := os.ReadFile("tachodata.ddd") if err != nil { log.Fatalf("read file: %v", err) } var vu decoder.Vu verified, err := decoder.UnmarshalTV(data, &vu) if err != nil { log.Fatalf("parse error: %v", err) } fmt.Printf("Verified: %v\n", verified) fmt.Printf("VIN (1st gen): %s\n", vu.VuOverviewFirstGen.VehicleIdentificationNumber.String()) // Pretty-print the entire decoded structure as JSON out, _ := json.MarshalIndent(vu, "", " ") fmt.Println(string(out)) // Example: access driver activity records for _, act := range vu.VuActivitiesFirstGen { decoded := act.VuActivityDailyData.ActivityChangeInfo for _, change := range decoded { info := change.Decode() fmt.Printf(" WorkType=%d Minutes=%d Driver=%v\n", info.WorkType, info.Minutes, info.Driver) } } } ``` -------------------------------- ### decoder.UnmarshalTLV Source: https://context7.com/traconiq/tachoparser/llms.txt Decodes TLV-encoded driver card binary data into a decoder.Card struct and verifies signatures. It returns a boolean indicating verification status and an error if parsing fails. ```APIDOC ## decoder.UnmarshalTLV — Parse Driver Card data ### Description Decodes TLV-encoded (Tag-Length-Value) driver card binary data into a `decoder.Card` struct and verifies signatures. Returns `(verified bool, err error)`. ### Method Signature `func UnmarshalTLV(data []byte, card *Card) (verified bool, err error)` ### Parameters - **data** ([]byte) - The raw driver card binary data. - **card** (*Card) - A pointer to a `decoder.Card` struct to populate with the decoded data. ### Returns - **verified** (bool) - True if all digital signatures are successfully verified, false otherwise. - **err** (error) - An error object if parsing or verification fails, nil otherwise. ### Request Example (Go) ```go package main import ( "encoding/json" "fmt" "log" "os" _ "github.com/traconiq/tachoparser/internal/pkg/certificates" "github.com/traconiq/tachoparser/pkg/decoder" ) func main() { data, err := os.ReadFile("drivercard.ddd") if err != nil { log.Fatalf("read file: %v", err) } var card decoder.Card verified, err := decoder.UnmarshalTLV(data, &card) if err != nil { log.Fatalf("parse error: %v", err) } fmt.Printf("Verified: %v\n", verified) // Access driver identification (1st gen fields) id1 := card.CardIdentificationAndDriverCardHolderIdentificationFirstGen fmt.Printf("Driver: %s %s\n", id1.DriverCardHolderIdentification.CardHolderName.HolderFirstNames.String(), id1.DriverCardHolderIdentification.CardHolderName.HolderSurname.String()) fmt.Printf("Card number: %s\n", id1.CardIdentification.CardNumber.String()) // Decode driver activity records dailyRecords := card.CardDriverActivityFirstGen.Decode() for _, day := range dailyRecords { fmt.Printf("Date: %v Distance: %d km\n", day.ActivityRecordDate.Decode(), day.ActivityDayDistance) } out, _ := json.MarshalIndent(card, "", " ") fmt.Println(string(out)) } ``` ``` -------------------------------- ### decoder.UnmarshalTV Source: https://context7.com/traconiq/tachoparser/llms.txt Decodes raw TV-encoded Vehicle Unit (VU) tachograph binary data into a decoder.Vu struct and verifies embedded digital signatures. It returns a boolean indicating verification status and an error if parsing fails. ```APIDOC ## decoder.UnmarshalTV — Parse Vehicle Unit data ### Description Decodes raw TV-encoded (Tag-Value) VU tachograph binary data into a `decoder.Vu` struct and simultaneously verifies all embedded digital signatures against loaded ERCA certificates. Returns `(verified bool, err error)`. ### Method Signature `func UnmarshalTV(data []byte, vu *Vu) (verified bool, err error)` ### Parameters - **data** ([]byte) - The raw tachograph VU binary data. - **vu** (*Vu) - A pointer to a `decoder.Vu` struct to populate with the decoded data. ### Returns - **verified** (bool) - True if all digital signatures are successfully verified, false otherwise. - **err** (error) - An error object if parsing or verification fails, nil otherwise. ### Request Example (Go) ```go package main import ( "encoding/json" "fmt" "log" "os" _ "github.com/traconiq/tachoparser/internal/pkg/certificates" // loads ERCA PKs at init "github.com/traconiq/tachoparser/pkg/decoder" ) func main() { data, err := os.ReadFile("tachodata.ddd") if err != nil { log.Fatalf("read file: %v", err) } var vu decoder.Vu verified, err := decoder.UnmarshalTV(data, &vu) if err != nil { log.Fatalf("parse error: %v", err) } fmt.Printf("Verified: %v\n", verified) fmt.Printf("VIN (1st gen): %s\n", vu.VuOverviewFirstGen.VehicleIdentificationNumber.String()) // Pretty-print the entire decoded structure as JSON out, _ := json.MarshalIndent(vu, "", " ") fmt.Println(string(out)) // Example: access driver activity records for _, act := range vu.VuActivitiesFirstGen { decoded := act.VuActivityDailyData.ActivityChangeInfo for _, change := range decoded { info := change.Decode() fmt.Printf(" WorkType=%d Minutes=%d Driver=%v\n", info.WorkType, info.Minutes, info.Driver) } } } ``` ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.