Industrial case study

MajidTek S7 — starting a concrete plant from modern software instead of a 1990s desktop program.

A batching plant was locked to a legacy Visual Basic program that spoke a proprietary telegram protocol to its Siemens-compatible PLC. We reverse-engineered the protocol from live captures, built a .NET 10 plant client that reads the plant and sends production orders, and put a web dashboard, API and admin panel on top — the mixer now starts from our software.

Industry
Construction materials — ready-mix concrete
Hardware
VIPA Speed7 PLC (S7-300 class), ELBAMATIC plant
Users
Plant operators, production managers, owners
Milestone
First app-driven batch on the live plant, August 2026
.NET 10 WPF AGLink (S7) Blazor ASP.NET Core API SQL Server Legacy Access migration xUnit
MajidTek S7 — production control
MajidTek S7 — production control with live weighing and dosing
How it works

From undocumented bytes to a running mixer.

No vendor documentation existed. Everything below was proven against the live plant, and every protocol rule is locked in by automated tests that assert on real captured bytes. Screens are from the real system; client and customer details are blurred.

Decoding a mailbox protocol nobody documented
Protocol reverse-engineering

Decoding a mailbox protocol nobody documented

The PC and the PLC exchange fixed-layout telegrams through one data block: a two-letter command, a length, and a payload of weights, silo numbers and mixing times. We captured live traffic, decoded the layout field by field, and found the encoders the decompiled legacy code had misled us about. The PLC log shows every poll and fault next to the raw telegram.

  • Seven command types, every length confirmed live
  • Handshake: the PLC blanks the command bytes when it consumes a telegram
  • Live PLC log with faults, warnings and decoded scale values
  • Live data overrules the decompile — a rule we learned the hard way
Every scale, live, on the way to the mixer
Weighing and dosing

Every scale, live, on the way to the mixer

Aggregate, filler, silica, water, additive and ice each get a live card with fill level, weight, target and the difference per material. Animated lines show what is flowing to the mixer, and mixing time, mixer gate and moisture correction sit right below.

  • Six scales with target versus actual per material
  • Flow lines to the mixer that follow the real dosing
  • PLC faults shown as a banner, acknowledged with F8
  • Mixing time, gate opening and concrete temperature
A start makes real concrete, so every gate is explicit
Safety

A start makes real concrete, so every gate is explicit

Starting the mixer from outside the plant is disarmed by default; an admin arms it for a fixed window and it disarms itself when the timer ends. Each plant has its own token, and the client writes the order body first and the command bytes last so the PLC never acts on a half-written order.

  • Remote start disarmed by default; arm for 15 minutes to 8 hours
  • Per-plant token for the plant client
  • Confirmation listing every weight, then a fresh re-read
  • Preview mode that writes nothing to the PLC
Silo levels for every material
Material stock

Silo levels for every material

The plant client pushes live values to a REST API, and the stock view shows every aggregate, cement, water and additive silo with its level and running balance. Production data reaches the browser from anywhere, backed by SQL Server with JWT security.

  • Aggregates, filler, water and additive silos at a glance
  • Running balance per silo, updated from the plant
  • Warning when production data is not being transmitted
  • Legacy Access database migrated to SQL Server
Recipes and machine timings, editable in one place
Recipes and timings

Recipes and machine timings, editable in one place

Concrete recipes carry strength class, water-cement factor, mixing and dry-mixing times and the weight per cubic metre for every aggregate, filler, water and additive — imported from the old system. The batching and mixer timings that the PLC uses are edited in the same app.

  • Recipes imported from the legacy recipe file
  • Admixture dosed as a percentage of cement weight
  • Batching times per material: aggregates, cement, water, additive, ice, silica
  • Mixer gate and discharge timings
Design the printed delivery ticket visually
Delivery tickets

Design the printed delivery ticket visually

Plants print onto pre-printed paper, so the ticket designer lays every field — ticket number, customer, site, mix, quantities, truck, driver and the materials table — over a scan of the real form, in millimetres, and saves it per plant.

  • Drag fields onto the ticket, show or hide each one
  • Millimetre rulers, zoom and undo
  • Paper size and background per ticket template
  • Only the black text is printed — the form is already on the paper
dotnet test 56 passed
✓ PutL_matches_the_live_plant_big_endian
✓ Real_EL_start_telegram_decodes_field_for_field
✓ LooksLikeOrder_accepts_a_real_order_and_rejects_everything_else
✓ MailboxReady_accepts_spaces_and_zeros_but_not_a_command
✓ BuildAck_matches_the_captured_EQ_telegram
✓ DosingOffsets_cover_every_weight_channel
… 50 more
Verification

Tests that assert on real captured bytes

Industrial code cannot be tested by trial on the plant. The protocol codec is pure and fully covered: the real start telegram decodes field by field, the encoders reproduce eight captured weights exactly, and two bugs that once cost days can never return.

  • Pure codec with no PLC dependency
  • Captured telegrams archived with decoded notes
  • A backup of the exact build that started the plant
  • 14-page technical documentation handed over
1
Live plant started from the new software
7
PLC command types decoded and verified
56
Automated tests, all green
0
Vendor documentation needed

Ready to ship something worth talking about?

Tell us the rough shape of your idea. We'll come back within one business day with a candid take — whether it's a fit, what it would take, and what we'd build first.

An unhandled error has occurred. Reload 🗙
MajidTek logo MajidTek ماجد تك
Connecting You are offline Disconnected Paused

Reconnecting… Still trying… Connection lost Session paused Couldn't resume

The connection to MajidTek dropped for a moment. Hold on, we're bringing it back. Next attempt in 0 s. You can also retry now. We couldn't reach the server. Check your internet connection, then retry or reload the page. The server paused this session to save resources. Resume to continue where you left off. The session could not be resumed. Retry or reload the page.

Your place on the page is kept while we reconnect.