@shyntech-proximity/sensor-app 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +270 -0
  2. package/index.js +143 -0
  3. package/package.json +19 -0
package/README.md ADDED
@@ -0,0 +1,270 @@
1
+ # Proximity Sensor Service
2
+
3
+ The **Proximity Sensor Service** is a real-time physical–digital bridge that ingests **radio proximity signals** (Wi-Fi, Wi-Fi Direct, BLE) from nearby devices and resolves **nearby vendors and inventories** using SSID / identifier matching.
4
+
5
+ It enables **hyperlocal discovery**, **foot-traffic monetization**, and **ambient commerce** without user interaction.
6
+
7
+ ---
8
+
9
+ ## 1. Scope & Responsibilities
10
+
11
+ ### What this service does
12
+
13
+ | Area | Responsibility |
14
+ | -------------------- | -------------------------------------------- |
15
+ | Signal ingestion | Receive Wi-Fi / Wi-Fi P2P / BLE scan data |
16
+ | Persistence | Store scan events for analytics & replay |
17
+ | Proximity resolution | Match detected identifiers to vendors |
18
+ | Caching | Maintain fast, short-lived proximity state |
19
+ | Web relay | Serve nearby vendor inventory to web clients |
20
+
21
+ ### What this service does NOT do
22
+
23
+ | Excluded | Reason |
24
+ | ------------------ | ------------------------------------ |
25
+ | Vendor CRUD | Handled by Vendor service |
26
+ | Inventory mutation | Read-only from proximity perspective |
27
+ | Authentication | Sensors are assumed trusted |
28
+ | Payments | Out of scope |
29
+
30
+ ---
31
+
32
+ ## 2. Supported Proximity Technologies
33
+
34
+ | Technology | Status | Purpose | Matching Key |
35
+ | ---------------------- | ------------- | ------------------------ | ---------------- |
36
+ | **Wi-Fi** | ✅ Implemented | Primary proximity signal | SSID |
37
+ | **Wi-Fi Direct (P2P)** | ✅ Implemented | Peer discovery, mesh | SSID / Device ID |
38
+ | **BLE** | 🟡 Planned | Ultra-low power beacons | UUID / MAC |
39
+
40
+ ---
41
+
42
+ ## 3. High-Level Architecture
43
+
44
+ | Component | Role |
45
+ | ----------------------- | --------------------------- |
46
+ | Native proximity device | Scans radio environment |
47
+ | Socket server | Real-time ingestion |
48
+ | DeviceScan store | Historical scan persistence |
49
+ | Vendor store | Known physical endpoints |
50
+ | Proximity cache | Low-latency resolution |
51
+ | Web socket namespace | Frontend notifications |
52
+
53
+ ---
54
+
55
+ ## 4. Socket Namespaces
56
+
57
+ ### Namespace Overview
58
+
59
+ | Namespace | Client Type | Purpose |
60
+ | ------------------- | ------------------ | -------------------------------- |
61
+ | `/proximity/native` | IoT / Edge devices | Send scan results |
62
+ | `/proximity/web` | Browser clients | Trigger & receive proximity data |
63
+
64
+ ---
65
+
66
+ ## 5. Socket Event Matrix
67
+
68
+ ### Server → Device
69
+
70
+ | Event | Frequency | Description |
71
+ | ---------------- | --------- | ----------------------- |
72
+ | `start_scanning` | Every 4s | Requests new scan cycle |
73
+
74
+ ---
75
+
76
+ ### Device → Server (Wi-Fi)
77
+
78
+ | Event | Payload | Description |
79
+ | ------------------- | ------------------ | ------------------- |
80
+ | `wifi::scan_result` | Wi-Fi scan payload | Standard Wi-Fi scan |
81
+
82
+ ---
83
+
84
+ ### Device → Server (Wi-Fi P2P)
85
+
86
+ | Event | Payload | Description |
87
+ | ---------------------- | ---------------- | --------------------- |
88
+ | `wifip2p::scan_result` | P2P scan payload | Mesh / peer discovery |
89
+
90
+ ---
91
+
92
+ ### Web Client Events
93
+
94
+ | Event | Direction | Description |
95
+ | -------------------------- | ------------ | ------------------------ |
96
+ | `PROXIMITY_SCAN::RUN_SCAN` | Web → Server | Trigger proximity lookup |
97
+ | `PROXIMITY_SCAN` | Server → Web | Return nearby vendors |
98
+
99
+ ---
100
+
101
+ ## 6. REST API Surface
102
+
103
+ ### Endpoint Summary
104
+
105
+ | Method | Endpoint | Purpose |
106
+ | ------ | -------------------------- | ---------------------- |
107
+ | GET | `/api/proximity/inventory` | Resolve nearby vendors |
108
+
109
+ ---
110
+
111
+ ### Identification Headers
112
+
113
+ | Header | Optional | Purpose |
114
+ | -------------- | -------- | --------------------------- |
115
+ | `x-device-sig` | Yes | Persistent device signature |
116
+ | `public_ip` | Yes | Network-level identity |
117
+ | `x-ws-token` | Yes | WebSocket fallback |
118
+
119
+ > The service automatically selects the **best available key**.
120
+
121
+ ---
122
+
123
+ ## 7. Proximity Resolution Flow
124
+
125
+ | Step | Action |
126
+ | ---- | ------------------------------ |
127
+ | 1 | Device performs scan |
128
+ | 2 | Scan results sent via socket |
129
+ | 3 | Scan persisted to database |
130
+ | 4 | SSIDs / identifiers extracted |
131
+ | 5 | Vendors matched by identifiers |
132
+ | 6 | Result cached |
133
+ | 7 | Web client requests inventory |
134
+ | 8 | Cached vendors returned |
135
+
136
+ ---
137
+
138
+ ## 8. Data Models
139
+
140
+ ### 8.1 Wi-Fi / Wi-Fi P2P Scan Payload
141
+
142
+ | Field | Type | Required | Description |
143
+ | ----------------- | ---------- | -------- | -------------------- |
144
+ | `device_id` | string | No | Device identifier |
145
+ | `deviceSignature` | string | No | Persistent signature |
146
+ | `public_ip` | string | No | Network IP |
147
+ | `timestamp` | ISO string | Yes | Scan time |
148
+ | `scan_meta` | object | No | Scan metadata |
149
+ | `detected_wifi` | array | Yes | Detected networks |
150
+
151
+ ---
152
+
153
+ ### 8.2 Detected Network
154
+
155
+ | Field | Type | Description |
156
+ | ----------- | ------ | ----------------- |
157
+ | `ssid` | string | Network name |
158
+ | `rssi` | number | Signal strength |
159
+ | `frequency` | number | Channel frequency |
160
+
161
+ ---
162
+
163
+ ### 8.3 BLE Scan Payload (Planned)
164
+
165
+ | Field | Type | Description |
166
+ | ----------- | ------ | -------------------- |
167
+ | `device_id` | string | BLE scanner |
168
+ | `beacons` | array | Detected BLE beacons |
169
+ | `uuid` | string | Beacon UUID |
170
+ | `major` | number | Beacon major |
171
+ | `minor` | number | Beacon minor |
172
+ | `rssi` | number | Signal strength |
173
+
174
+ ---
175
+
176
+ ## 9. Proximity Cache Structure
177
+
178
+ | Key | Description |
179
+ | -------------- | ------------------------- |
180
+ | `ssids` | Last detected identifiers |
181
+ | `timestamp` | Last scan time |
182
+ | `socketId` | Active connection |
183
+ | `persistentId` | Device identity |
184
+
185
+ ---
186
+
187
+ ## 10. Vendor Matching Logic
188
+
189
+ | Signal Type | Matching Strategy |
190
+ | ----------- | -------------------------------------- |
191
+ | Wi-Fi | SSID ∈ Vendor.SSID |
192
+ | Wi-Fi P2P | SSID ∈ Vendor.SSID |
193
+ | BLE | UUID ↔ Vendor beacon mapping (planned) |
194
+
195
+ ---
196
+
197
+ ## 11. Error Handling Matrix
198
+
199
+ | Scenario | Response |
200
+ | ----------------- | ------------------ |
201
+ | Invalid payload | Error ACK |
202
+ | Empty scan | `stores_count = 0` |
203
+ | No vendor match | Valid empty result |
204
+ | DB failure | Error + logged |
205
+ | Socket disconnect | Scan loop stopped |
206
+
207
+ ---
208
+
209
+ ## 12. Security Model
210
+
211
+ | Aspect | Current State |
212
+ | ----------------- | --------------- |
213
+ | Authentication | None |
214
+ | Authorization | None |
215
+ | Trust model | Device-based |
216
+ | Replay protection | Timestamp-based |
217
+ | Rate limiting | Not implemented |
218
+
219
+ > Designed for **trusted edge devices**. Hardenable later.
220
+
221
+ ---
222
+
223
+ ## 13. Local Development
224
+
225
+ ### Requirements
226
+
227
+ | Dependency | Version |
228
+ | ---------- | ------- |
229
+ | Node.js | ≥ 18 |
230
+ | MongoDB | ≥ 5 |
231
+ | Socket.IO | v4 |
232
+
233
+ ---
234
+
235
+ ### Run Locally
236
+
237
+ ```bash
238
+ npm install
239
+ npm run dev
240
+ ```
241
+
242
+ ---
243
+
244
+ ## 14. Future Enhancements
245
+
246
+ | Feature | Status |
247
+ | ------------------------ | ------- |
248
+ | BLE beacon ingestion | Planned |
249
+ | Movement delta detection | Planned |
250
+ | Confidence scoring | Planned |
251
+ | Multi-sensor fusion | Planned |
252
+ | Edge mesh propagation | Planned |
253
+
254
+ ---
255
+
256
+ ## 15. Related Docs
257
+
258
+ | Document | Purpose |
259
+ | -------------- | ----------------------------- |
260
+ | `openapi.yaml` | REST API spec |
261
+ | Vendor API | Vendor & inventory management |
262
+ | QA Matrix | Test coverage |
263
+ | SRS | Functional requirements |
264
+
265
+ ---
266
+
267
+ ## 16. Ownership
268
+
269
+ **Proximity Platform – Sensor Layer**
270
+ Built for **ambient, real-world intelligence**.
package/index.js ADDED
@@ -0,0 +1,143 @@
1
+ import { DeviceScan } from "../models/DeviceScan.js";
2
+ import { Vendor } from "../models/Vendor.js";
3
+ import axios from "axios";
4
+
5
+
6
+
7
+ export const initSocket = (io, proximityCache) => {
8
+ const nativeNamespace = io.of("/proximity/native");
9
+
10
+ nativeNamespace.on("connection", (socket) => {
11
+ const persistentId = socket.handshake.query.persistentId || socket.id;
12
+ console.log(`Proximity device connected: ${persistentId} (socket: ${socket.id})`);
13
+
14
+ // Send periodic scan requests
15
+ const scan = () => { console.log("[EMITTING SCAN REQUEST]"); socket.emit("start_scanning");}
16
+ const scanInterval = setInterval(scan, 4000);
17
+
18
+ // Receive scan result from proximity sensor
19
+ socket.on("wifi::scan_result", async (payload, ack) => {
20
+ try {
21
+ const { device_id, public_ip, detected_wifi, timestamp, scan_meta, deviceSignature } = payload;
22
+
23
+ // Choose best available unique key for device
24
+ const key = public_ip || deviceSignature || persistentId;
25
+
26
+ console.log(`[SCAN RESULT] From ${persistentId}:`, {
27
+ detected_wifi_count: detected_wifi?.length || 0,
28
+ ...payload
29
+ });
30
+
31
+ // Save scan data
32
+ await DeviceScan.create({
33
+ device_id,
34
+ public_ip,
35
+ detected_wifi,
36
+ timestamp,
37
+ scan_meta,
38
+ });
39
+
40
+ // Find nearby stores by SSID
41
+ const ssids = (detected_wifi || []).map((w) => w.ssid);
42
+ const stores = await Vendor.find({ ssid: { $in: ssids } }).lean();
43
+
44
+
45
+ // Check if that there's any changes between current datapoint and previous datapoints/
46
+ // Data points are dectected current and previous {stores, devicescans} value
47
+
48
+
49
+ if (ack) ack({ status: "ok", stores_count: stores.length });
50
+ } catch (e) {
51
+ console.error("scan_result error:", e);
52
+ if (ack) ack({ status: "error", error: e.message });
53
+ }
54
+ });
55
+
56
+
57
+ // === Receive Wi-Fi Direct scan results from nearby nodes ===
58
+ socket.on("wifip2p::scan_result", async (payload, ack) => {
59
+ console.log(payload)
60
+ try {
61
+ const {
62
+ device_id, public_ip, detected_wifi, timestamp, scan_meta, deviceSignature,
63
+ } = payload || {};
64
+
65
+ const key = public_ip || deviceSignature || persistentId;
66
+ const wifiCount = detected_wifi?.length || 0;
67
+
68
+ console.log(`📶 [SCAN RESULT] From ${device_id || "unknown"} →`, {
69
+ detected_wifi_count: wifiCount,
70
+ timestamp,
71
+ scan_meta,
72
+ });
73
+
74
+ // 🧠 Save scan data (to DB, file, or local storage)
75
+ await DeviceScan.create({
76
+ device_id,
77
+ public_ip,
78
+ detected_wifi,
79
+ timestamp,
80
+ scan_meta,
81
+ });
82
+
83
+ // 🏪 Identify known SSIDs linked to nearby “stores” or endpoints
84
+ const ssids = (detected_wifi || []).map((w) => w.ssid).filter(Boolean);
85
+ const stores = await Vendor.find({ ssid: { $in: ssids } }).lean();
86
+
87
+ // 🔒 Cache the device’s proximity data for rapid local queries
88
+ proximityCache[key] = {
89
+ ssids,
90
+ timestamp: Date.now(),
91
+ socketId: socket.id,
92
+ persistentId,
93
+ };
94
+
95
+ // ✅ Respond back to sender (ACK)
96
+ if (ack) ack({ status: "ok", stores_count: stores.length });
97
+
98
+ console.log(`✅ [Processed] ${wifiCount} networks, ${stores.length} matches.`);
99
+ } catch (e) {
100
+ console.error("❌ scan_result error:", e);
101
+ if (ack) ack({ status: "error", error: e.message });
102
+ }
103
+ });
104
+
105
+
106
+ socket.on("disconnect", () => {
107
+ console.log(`Device disconnected: ${persistentId} (socket: ${socket.id})`);
108
+ clearInterval(scanInterval);
109
+ });
110
+ });
111
+
112
+
113
+
114
+
115
+ const webNamespace = io.of("/proximity/web");
116
+
117
+ webNamespace.on("connection", socket => {
118
+ console.log("Server=>WebClient Socket Connted", socket.id)
119
+ socket.on("PROXIMITY_SCAN::RUN_SCAN", async(payload)=>{
120
+ try{
121
+ const res = await axios.get("http://10.48.59.128:5000/api/proximity/inventory", {
122
+ headers: {
123
+ "x-device-sig": payload.persistentId,
124
+ //public_ip: await fetchPublicIP(),
125
+ },
126
+ })
127
+ console.log(payload)
128
+ if(res.data.length > 0){
129
+ console.log("[EMITTING RESULT TO WEB]")
130
+ socket.emit("PROXIMITY_SCAN", {data:res.data});
131
+ }
132
+ else if(res.data.length == 0){
133
+ console.log("[EMITTING RESULT TO WEB]")
134
+ console.log(res.data);
135
+ //socket.emit("PROXIMITY_SCAN", {data:res.data});
136
+ }
137
+ }catch(e){
138
+ console.log(payload?.persistentId)
139
+ }
140
+ })
141
+
142
+ })
143
+ };
package/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@shyntech-proximity/sensor-app",
3
+ "version": "1.0.0",
4
+ "main": "index.js",
5
+ "files": [
6
+ "dist",
7
+ "src"
8
+ ],
9
+ "scripts": {
10
+ "build": "",
11
+ "prepublishOnly": "npm run build"
12
+ },
13
+ "publishConfig": {
14
+ "@shyntech:registry": "https://gitlab.com/api/v4/projects/78157101/packages/npm/"
15
+ },
16
+ "devDependencies": {
17
+ "typescript": "^5.9.3"
18
+ }
19
+ }