Skip to content

Commit 09dd63c

Browse files
robertsLandoclaude
andcommitted
docs: expand CLAUDE.md with architecture guide and ASHRAE 135 references
Add protocol stack architecture, client flow documentation, testing tiers, key types, and links to official ASHRAE 135-2024/2020 standards. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 8150a2f commit 09dd63c

1 file changed

Lines changed: 118 additions & 29 deletions

File tree

CLAUDE.md

Lines changed: 118 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,128 @@
11
# CLAUDE.md
22

3-
This file provides guidance to Claude Code (claude.ai/code) when working with this repository.
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
44

5-
## Project Instructions
5+
## Project Overview
66

7-
All coding standards, architecture patterns, testing guidelines, and contribution requirements are maintained in a single shared location:
7+
`@bacnet-js/client` — a BACnet® protocol stack written in pure TypeScript for Node.js (>= 20). Implements ASHRAE 135 standard for building automation and control networks. Published as an npm package with only two runtime dependencies (`debug`, `iconv-lite`).
88

9-
**[.github/copilot-instructions.md](.github/copilot-instructions.md)**
9+
## Commands
1010

11-
That file is the primary reference for:
11+
```bash
12+
npm run build # TypeScript compile (tsconfig.build.json)
13+
npm run lint # ESLint check
14+
npm run lint:fix # ESLint auto-fix
1215

13-
- Code style and TypeScript conventions
14-
- Architecture patterns (event-driven design, buffer management, ASN.1 encoding)
15-
- BACnet protocol specifics
16-
- Testing strategy and coverage requirements
17-
- Git workflow and conventional commits
18-
- Pull request quality standards
16+
npm run test:all # All tests (unit + integration + compliance)
17+
npm run test:unit # Unit tests only
18+
npm run test:integration # Integration tests only
19+
npm run test:compliance # Compliance tests (requires emulator, runs sequentially)
1920

20-
## Quick Reference
21+
# Run a single test file
22+
node --require esbuild-register --test test/unit/service-read-property.spec.ts
2123

22-
```bash
23-
# Build
24-
npm run build
25-
26-
# Lint
27-
npm run lint
28-
npm run lint:fix
29-
30-
# Test
31-
npm run test:all # Run all tests
32-
npm run test:unit # Unit tests only
33-
npm run test:integration # Integration tests only
34-
npm run test:compliance # Compliance tests only
35-
36-
# Development
37-
npm run emulator:start # Start BACnet device emulator
38-
npm run docs # Generate API docs with TypeDoc
24+
npm run emulator:start # Start BACnet device emulator (needed for compliance tests)
25+
npm run docs # Generate TypeDoc API docs
26+
```
27+
28+
Tests use the **Node.js native test runner** (`node --test`) with `esbuild-register` for TypeScript. No Jest/Mocha.
29+
30+
## Architecture
31+
32+
### Protocol Stack (bottom-up)
33+
34+
Each layer is a pure-function module with `encode`/`decode` exports sharing a mutable `EncodeBuffer` (`{ buffer: Buffer, offset: number }`):
35+
36+
```
37+
UDP Socket (Transport)
38+
→ BVLC (src/lib/bvlc.ts) — 4-byte BACnet/IP framing header
39+
→ NPDU (src/lib/npdu.ts) — Network routing, source/dest addressing
40+
→ APDU (src/lib/apdu.ts) — PDU type dispatch (confirmed/unconfirmed/ack/error/abort)
41+
→ Service payload — Service-specific ASN.1 encoded data
42+
```
43+
44+
`src/lib/asn1.ts` provides all ASN.1 primitives (context/application tags, object IDs, bitstrings, etc.). Uses `iconv-lite` for multi-encoding character string support.
45+
46+
### Main Client (`src/lib/client.ts`)
47+
48+
`BACnetClient` extends `TypedEventEmitter<BACnetClientEvents>`. All BACnet services are methods on this class (~2100 lines).
49+
50+
**Outbound flow (e.g., readProperty):**
51+
1. Get rolling invoke ID (0-255)
52+
2. Allocate `EncodeBuffer`, encode NPDU → APDU → service payload
53+
3. Prepend BVLC header via `sendBvlc()`, send UDP
54+
4. `RequestManager.add(invokeId)` returns a Promise that resolves when ACK arrives
55+
56+
**Inbound flow:**
57+
1. `Transport` emits `message``_receiveData()`
58+
2. Decode BVLC → NPDU → determine PDU type
59+
3. For requests: look up service in `confirmedServiceMap`/`unconfirmedServiceMap`, call `ServiceClass.decode()`, emit event
60+
4. For ACKs: `RequestManager.resolve(invokeId, data)`
61+
62+
### Services (`src/lib/services/`)
63+
64+
Each service is a static class extending `BacnetService` (or `BacnetAckService`):
65+
66+
```typescript
67+
class ReadProperty extends BacnetAckService {
68+
static encode(buffer, ...) // Client sends request
69+
static decode(buffer, offset, len) // Client receives request (server role)
70+
static encodeAcknowledge(buffer, ...) // Client sends ACK (server role)
71+
static decodeAcknowledge(buffer, ...) // Client receives ACK
72+
}
73+
```
74+
75+
`ServicesMap` in `services/index.ts` maps event names (e.g., `"readProperty"`) to service classes for dynamic dispatch.
76+
77+
### Transport (`src/lib/transport.ts`)
78+
79+
Wraps a `dgram` UDP4 socket. Default port: `47808` (0xBAC0). Handles broadcast deduplication (10s window). Injectable via `ClientOptions.transport` for testing.
80+
81+
### RequestManager (`src/lib/request-manager.ts`)
82+
83+
Maps invoke IDs to `Deferred<NetworkOpResult>` promises. Handles timeout sweeping. Timeout function is injectable for test mocking.
84+
85+
### Key Entry Point (`src/index.ts`)
86+
87+
Thin re-export: `BACnetClient` as default export, plus all enums, types, and bitstring classes.
88+
89+
## Testing Tiers
90+
91+
- **Unit** (`test/unit/`): Encode/decode in isolation. Uses `getBuffer()` helper from `test/unit/utils.ts`.
92+
- **Integration** (`test/integration/`): Uses `TransportStub` (mock EventEmitter) injected into `BACnetClient`. Simulates packets via `transportStub.emit('message', buffer, addr)`.
93+
- **Compliance** (`test/compliance/`): Runs against the live emulator. Sequential execution (`--test-concurrency=1`).
94+
95+
## Key Types and Conventions
96+
97+
- `EncodeBuffer`: `{ buffer: Buffer, offset: number }` — mutable cursor passed through all encode layers
98+
- `BACNetObjectID`: `{ type: ObjectType, instance: number }`
99+
- `TypedValue<Tag>`: `{ type: ApplicationTag, value: ... }` — generic typed BACnet value
100+
- `Decode<T>`: `{ len, value }` — standard decode return shape
101+
- Enums in `src/lib/enum.ts`: `ObjectType`, `PropertyIdentifier`, `ApplicationTag`, `ConfirmedServiceChoice`, `UnconfirmedServiceChoice`, `PduType`, `ErrorClass`, `ErrorCode`
102+
- Bitstrings in `src/lib/bitstring.ts`: `GenericBitString<E>`, `StatusFlagsBitString`, `ServicesSupportedBitString`
103+
104+
## ASHRAE 135 Standard Reference
105+
106+
This library implements [ASHRAE Standard 135 (BACnet)](https://www.ashrae.org/technical-resources/standards-and-guidelines/read-only-versions-of-ashrae-standards). Always consult the official specification when reviewing or implementing features:
107+
108+
- **[Standard 135-2024](https://ashrae.iwrapper.com/ASHRAE_PREVIEW_ONLY_STANDARDS/STD_135_2024)** — Current version
109+
- **[Standard 135-2020](https://ashrae.iwrapper.com/ASHRAE_PREVIEW_ONLY_STANDARDS/STD_135_2020)** — Previous version
110+
111+
When implementing or modifying protocol features, reference the relevant standard section in a code comment with a link when possible. Example:
112+
113+
```typescript
114+
// Encode object identifier per ASHRAE 135-2024 §20.2.14
115+
// https://ashrae.iwrapper.com/ASHRAE_PREVIEW_ONLY_STANDARDS/STD_135_2024
116+
encodeApplicationObjectId(buffer, objectType, instance)
39117
```
118+
119+
## Coding Standards
120+
121+
Detailed standards are in **[.github/copilot-instructions.md](.github/copilot-instructions.md)**. Key points:
122+
123+
- Strict TypeScript (`noImplicitAny`, `strictNullChecks`)
124+
- Files: camelCase. Classes: PascalCase. Enums: PascalCase with ALL_CAPS values. Private members: underscore prefix.
125+
- `interface` over `type` for object shapes
126+
- Conventional Commits: `feat|fix|docs|test|chore|refactor|perf|ci[scope]: description`
127+
- Scopes: `client`, `transport`, `services`, `asn1`, `enum`, `types`, `apdu`, `npdu`, `bvlc`
128+
- Debug logging: `debug` library with `bacnet:module:level` namespaces

0 commit comments

Comments
 (0)