bt-seneca-msc
v0.4.2
Published
A pure Javascript API for the Seneca Multi Smart Calibrator (MSC) device, using web bluetooth.
Maintainers
Readme
bt-seneca-msc
A pure JavaScript API for the Seneca Multi Smart Calibrator (MSC) device, using Web Bluetooth from modern browsers.
🚀 Live Demo | 📖 Documentation | 🛠️ Getting Started
Table of Contents
- Overview
- Prerequisites
- Quick Start
- Installation
- API Reference
- Usage Examples
- Device Features
- Performance
- Development
- Troubleshooting
- Contributing
Overview
This package provides a complete JavaScript interface for the Seneca Multi Smart Calibrator device via Web Bluetooth. It implements Modbus RTU FC3/FC16 functions specifically designed to run in pure browser environments without Node.js dependencies.
✨ Key Features
- 🌐 Pure browser implementation using Web Bluetooth API
- 🔗 Modbus RTU protocol over Bluetooth
- ⚡ Real-time measurement and generation capabilities
- 🔄 Automatic device state management
- 🛡️ Comprehensive error handling and recovery
- 📱 Cross-platform support (Desktop & Mobile browsers)
🧪 Tested Environments
| Platform | Browser | Device | Status | |----------|---------|---------|---------| | Windows PC | Chrome/Edge | MSC firmware 1.0.44 | ✅ Tested | | Android | Chrome | Samsung S10 | ✅ Tested | | iOS | Safari | - | ❌ Not supported |
📋 Prerequisites
Browser Requirements
| Browser | Minimum Version | Notes | |---------|----------------|-------| | Chrome | 56+ | ✅ Full support | | Edge | 79+ | ✅ Full support | | Firefox | - | ❌ No Web Bluetooth support | | Safari | - | ❌ No Web Bluetooth support |
Note: "Experimental Web Platform Features" may need to be enabled in Chrome flags
Hardware Requirements
- ✅ Seneca Multi Smart Calibrator device (MSC series)
- ✅ Bluetooth-enabled device
- ⚠️ User gesture required for initial pairing (browser security requirement)
Quick Compatibility Check
if (!navigator.bluetooth) {
console.error('Web Bluetooth is not supported in this browser');
} else {
console.log('Web Bluetooth is available');
}🚀 Quick Start
1. Include the Library
<script src="https://cdn.jsdelivr.net/npm/bt-seneca-msc@latest/dist/bt-seneca-msc.min.js"></script>npm install bt-seneca-mscimport MSC from 'bt-seneca-msc';
// or
const MSC = require('bt-seneca-msc');2. Pair and Connect
// ⚠️ Must be called from a user gesture (button click, etc.)
document.getElementById('connectBtn').addEventListener('click', async () => {
try {
const paired = await MSC.Pair(true);
if (paired) {
console.log('Device connected successfully!');
}
} catch (error) {
console.error('Pairing failed:', error);
}
});3. Take a Measurement
async function measureVoltage() {
const state = await MSC.GetState();
if (state.ready) {
const command = MSC.Command.CreateNoSP(MSC.CommandType.V);
const result = await MSC.SimpleExecute(command);
if (!result.error) {
console.log(`Voltage: ${result.value} V`);
}
}
}📦 Installation
npm install bt-seneca-mscimport MSC from 'bt-seneca-msc';
// or
const MSC = require('bt-seneca-msc');<script src="https://cdn.jsdelivr.net/npm/bt-seneca-msc@latest/dist/bt-seneca-msc.min.js"></script>libman install bt-seneca-msc --provider jsdelivrDownload from the releases page and include the dist/bt-seneca-msc.min.js file.
📖 API Reference
Core Methods
MSC.Pair(force: boolean): Promise<boolean>
Pairs with a Bluetooth MSC device.
force: If true, always shows device picker; if false, reconnects to last device- Returns: Promise resolving to connection success
- Note: Must be called from user gesture
MSC.Stop(): Promise<boolean>
Disconnects Bluetooth and stops polling.
- Returns: Promise resolving to disconnection success
MSC.Execute(command: Command): Promise<Command>
Executes a command and returns updated command object.
command: Command object created withMSC.Command.CreateXXX()methods- Returns: Promise resolving to updated command with results
MSC.SimpleExecute(command: Command): Promise<CommandResult>
Executes command and returns simple result value.
- Returns: Promise resolving to
{error: boolean, value: any, message: string}
MSC.GetState(): Promise<MeterState>
Gets current device state and measurements.
- Returns: Promise resolving to complete device state
JSON API (ASP.NET Core Interop)
MSC.SimpleExecuteJSON(jsonCommand: string): Promise<string>
JSON version of SimpleExecute.
MSC.ExecuteJSON(jsonCommand: string): Promise<string>
JSON version of Execute.
MSC.GetStateJSON(): Promise<string>
JSON version of GetState.
Command Creation
MSC.Command.CreateNoSP(type: CommandType): Command
Creates command with no setpoints (measurements).
MSC.Command.CreateOneSP(type: CommandType, setpoint: number): Command
Creates command with one setpoint (single value generation).
MSC.Command.CreateTwoSP(type: CommandType, setpoint1: number, setpoint2: number): Command
Creates command with two setpoints (dual value generation).
State Properties
const state = await MSC.GetState();
// Connection status
state.ready // boolean: Device ready for commands
state.initializing // boolean: Device initializing
state.status // string: Current state machine status
// Data
state.lastMeasure // array: Latest measurement data
state.lastSetpoint // array: Latest generation setpoint data
// Device info
state.deviceName // string: Bluetooth device name
state.deviceSerial // string: MSC device serial number
state.deviceMode // string: Current device mode
state.batteryLevel // number: Battery voltage
state.stats // object: Debug statisticsDevice States
| State | Description | Next State |
|-------|-------------|------------|
| NOT_CONNECTED | Initial state before pairing | CONNECTING |
| CONNECTING | Waiting for pairing to complete | DEVICE_PAIRED |
| DEVICE_PAIRED | Pairing completed, no BT interface | SUBSCRIBING |
| SUBSCRIBING | Waiting for BT interfaces | METER_INIT |
| METER_INIT | Connected, initializing meter | METER_INITIALIZING |
| METER_INITIALIZING | Reading initial meter state | IDLE |
| IDLE | Ready to execute commands | BUSY |
| BUSY | Executing command or refreshing data | IDLE, ERROR |
| ERROR | Exception occurred | METER_INIT |
| STOPPING | Processing stop request | STOPPED |
| STOPPED | Everything stopped | - |
💡 Usage Examples
Basic Voltage Measurement
async function measureVoltage() {
try {
// Check if device is ready
const state = await MSC.GetState();
if (!state.ready) {
throw new Error('Device not ready');
}
// Create measurement command
const command = MSC.Command.CreateNoSP(MSC.CommandType.V);
const result = await MSC.SimpleExecute(command);
if (result.error) {
console.error('Measurement failed:', result.message);
} else {
console.log(`Voltage: ${result.value} V`);
}
} catch (error) {
console.error('Error:', error);
}
}Voltage Generation
async function generateVoltage(voltage) {
try {
const state = await MSC.GetState();
if (!state.ready) {
throw new Error('Device not ready');
}
// Create generation command
const command = MSC.Command.CreateOneSP(MSC.CommandType.GEN_V, voltage);
const result = await MSC.Execute(command);
if (result.error) {
console.error('Generation failed');
} else {
console.log(`Generating ${voltage}V`);
// Monitor generation status
const newState = await MSC.GetState();
if (newState.lastSetpoint.error) {
console.error('Generation error detected');
}
}
} catch (error) {
console.error('Error:', error);
}
}Pulse Generation
async function generatePulses(count, frequency) {
try {
// Set voltage levels first
await MSC.Execute(MSC.Command.CreateOneSP(MSC.CommandType.SET_Ulow, 0.0));
await MSC.Execute(MSC.Command.CreateOneSP(MSC.CommandType.SET_Uhigh, 5.0));
// Generate pulses (count, frequency in Hz)
const command = MSC.Command.CreateTwoSP(MSC.CommandType.GEN_PulseTrain, count, frequency);
const result = await MSC.Execute(command);
if (!result.error) {
console.log(`Generating ${count} pulses at ${frequency} Hz`);
}
} catch (error) {
console.error('Pulse generation failed:', error);
}
}Continuous Monitoring
async function startMonitoring() {
setInterval(async () => {
try {
const state = await MSC.GetState();
if (state.ready && state.lastMeasure && !state.lastMeasure.error) {
console.log('Current measurement:', state.lastMeasure[0]);
}
if (state.lastSetpoint && !state.lastSetpoint.error) {
console.log('Current setpoint:', state.lastSetpoint[0]);
}
} catch (error) {
console.error('Monitoring error:', error);
}
}, 1000);
}🔧 Device Features
Measurements
| Function | Status | Data Returned | |----------|--------|---------------| | V, mV readings | ✅ Tested | Instantaneous, min, max values | | mA active/passive | ✅ Tested | Instantaneous, min, max values | | RTD 2W readings | ✅ Tested | Temperature (°C) and resistance (Ω) | | Thermocouples 2W/3W/4W | ✅ Not tested | Temperature (°C) | | Frequency reading | ✅ Tested | Leading/falling edge frequency | | Pulse counting | ✅ Tested 0-10kHz | Leading/falling edge counts | | Load cell | ✅ Not tested | Imbalance mV/V |
Generation
| Function | Status | Setpoint | |----------|--------|----------| | V, mV generation | ✅ Tested | Voltage (mV/V) | | mA active/passive | ⚠️ Basic testing | Current (mA) | | RTD 2W simulation | ✅ Not tested | Temperature (°C) | | Thermocouple simulation | ✅ Not tested | Temperature (°C) | | Frequency generation | ✅ Tested 0-10kHz | LE and FE frequency (Hz) | | Pulse generation | ✅ Tested 1kHz | LE and FE frequency (Hz) | | Load cell simulation | ✅ Not tested | Imbalance mV/V |
Configuration Settings
| Setting | Command | Range | Status |
|---------|---------|-------|--------|
| Low level voltage | SET_Ulow | 0-27V | ✅ Tested |
| High level voltage | SET_Uhigh | 0-27V | ✅ Tested |
| Pulse width threshold | SET_Sensitivity_uS | 1-∞ μs | ⚠️ Not tested |
| Voltage threshold | SET_UThreshold_F | 0-27V | ⚠️ Not tested |
| Cold junction compensation | SET_ColdJunction | Various | ⚠️ Not tested |
Not Implemented Features
- Ramps editing and application
- Data logging start/stop
- Logged data retrieval
- Clock read/sync
- Firmware version read
- mV/V to kg conversion
- Automatic switch off delay
Performance
| Operation | Typical Time | Notes | |-----------|--------------|-------| | Device pairing | 20-40s | Multiple attempts to establish characteristics | | Command execution | 2-3s | From command to device response | | Measurement refresh | ~1s | Updated min/max/current values | | Generation refresh | ~1s | Updated setpoint and error status | | Modbus roundtrip | ~150ms | Single command/response cycle |
Polling Frequency: 750ms automatic state refresh when idle
Development
Building
# Install dependencies
npm install
# Development build (unminified)
npm run dev
# Production build (minified)
npm run distTesting
# Run tests with coverage
npm test
# Verbose test output
npm test -- --verboseNote: Tests use captured Modbus RTU packet traces in hex format for simulation, allowing comprehensive testing without physical hardware.
Project Structure
src/
├── classes/ # Core classes
│ ├── SenecaMSC.js # Main Bluetooth/Modbus operations
│ ├── APIState.js # State management
│ ├── Command.js # Command structure
│ └── ...
├── bluetooth.js # Web Bluetooth wrapper
├── modbusRtu.js # Modbus RTU protocol
├── senecaModbus.js # Seneca-specific commands
└── constants.js # Enums and constantsCI/CD
- Main branch: Triggers GitHub Actions for CI and NPM publishing
- Development branch: Use for feature development, PR to main when ready
- GitHub Pages: Sample application updates on main branch pushes
- NPM: Automatic publishing when package.json version changes
Troubleshooting
Common Issues
"Web Bluetooth is not available"
- Ensure you're using a supported browser (Chrome 56+, Edge 79+)
- Check that Bluetooth is enabled on your device
- Try enabling "Experimental Web Platform Features" in Chrome flags
"User cancelled the requestDevice() chooser"
- User must manually select device from browser dialog
- Ensure MSC device is powered on and discoverable
- Device name should start with "MSC"
"Device pairing takes too long"
- This is normal (20-40s typical)
- Ensure MSC device remains powered during pairing
- Try moving closer to the device
"Commands fail after successful pairing"
- Check device battery level (
state.batteryLevel) - Verify device is not in error state
- Try disconnecting and reconnecting
"Measurements show error flag"
- Check device connections and probes
- Verify measurement range is appropriate
- Check for overcurrent/overvoltage conditions
Debug Information
Enable debug logging:
const state = await MSC.GetState();
console.log('Debug stats:', state.stats);Getting Help
- Check the live demo for working examples
- Review browser console for error messages
- Ensure proper user gesture handling for pairing
- Verify device compatibility and firmware version
Contributing
- Fork the repository
- Create a feature branch from
development - Make your changes with tests
- Submit a pull request to
developmentbranch
Development Workflow
- Use
developmentbranch for features - PR to
mainwhen ready for release - Tests must pass and maintain coverage
- Follow existing code style and patterns
License
MIT License - see LICENSE file for details.
Seneca MSC Device Information: https://www.seneca.it/msc/
