CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-sintef-jarduino--org-sintef-jarduino

A comprehensive Java library for interfacing with Arduino boards through serial, Bluetooth, and Ethernet connections

Overview
Eval results
Files

message-handling.mddocs/

Message Handling and Observers

Observer pattern implementation for asynchronous Arduino message handling with strongly-typed message classes and automatic parsing. This system enables decoupled communication between Arduino hardware and Java applications through a publish-subscribe model.

Capabilities

Observer Pattern Interfaces

Core observer interfaces for Arduino message handling enabling asynchronous, event-driven communication.

interface JArduinoObserver {
    void receiveMsg(byte[] msg);
}

interface JArduinoSubject {
    void register(JArduinoObserver observer);
    void unregister(JArduinoObserver observer);
}

interface JArduinoClientObserver {
    void receiveMsg(byte[] msg);
}

interface JArduinoClientSubject {
    void register(JArduinoClientObserver observer);
    void unregister(JArduinoClientObserver observer);
}

Comprehensive Message Handler Interface

Complete interface for handling all types of Arduino messages with strongly-typed method signatures.

interface IJArduinoMessageHandler {
    // Command handlers
    void handlePinMode(PinModeMsg msg);
    void handleDigitalRead(DigitalReadMsg msg);
    void handleDigitalWrite(DigitalWriteMsg msg);
    void handleAnalogReference(AnalogReferenceMsg msg);
    void handleAnalogRead(AnalogReadMsg msg);
    void handleAnalogWrite(AnalogWriteMsg msg);
    void handleTone(ToneMsg msg);
    void handleNoTone(NoToneMsg msg);
    void handlePulseIn(PulseInMsg msg);
    void handlePing(PingMsg msg);
    void handleAttachInterrupt(AttachInterruptMsg msg);
    void handleDetachInterrupt(DetachInterruptMsg msg);
    void handleEeprom_read(Eeprom_readMsg msg);
    void handleEeprom_sync_write(Eeprom_sync_writeMsg msg);
    void handleEeprom_write(Eeprom_writeMsg msg);

    // Result handlers
    void handleDigitalReadResult(DigitalReadResultMsg msg);
    void handleAnalogReadResult(AnalogReadResultMsg msg);
    void handlePulseInResult(PulseInResultMsg msg);
    void handlePong(PongMsg msg);
    void handleInterruptNotification(InterruptNotificationMsg msg);
    void handleEeprom_value(Eeprom_valueMsg msg);
    void handleEeprom_write_ack(Eeprom_write_ackMsg msg);
}

Abstract Message Handler Classes

Base implementations providing partial message handling functionality.

abstract class JArduinoMessageHandler implements IJArduinoMessageHandler;
abstract class JArduinoClientMessageHandler implements IJArduinoMessageHandler;

Strongly-Typed Message Classes

Complete set of message classes for all Arduino operations, providing type safety and automatic serialization.

// Command messages
class PinModeMsg extends JArduinoProtocolPacket {
    DigitalPin getPin();
    PinMode getMode();
}

class DigitalReadMsg extends JArduinoProtocolPacket {
    DigitalPin getPin();
}

class DigitalWriteMsg extends JArduinoProtocolPacket {
    DigitalPin getPin();
    DigitalState getValue();
}

class AnalogReadMsg extends JArduinoProtocolPacket {
    AnalogPin getPin();
}

class AnalogWriteMsg extends JArduinoProtocolPacket {
    PWMPin getPin();
    byte getValue();
}

class AnalogReferenceMsg extends JArduinoProtocolPacket {
    AnalogReference getReference();
}

class ToneMsg extends JArduinoProtocolPacket {
    DigitalPin getPin();
    short getFrequency();
    short getDuration();
}

class NoToneMsg extends JArduinoProtocolPacket {
    DigitalPin getPin();
}

class PulseInMsg extends JArduinoProtocolPacket {
    DigitalPin getPin();
    DigitalState getState();
}

class AttachInterruptMsg extends JArduinoProtocolPacket {
    InterruptPin getInterrupt();
    InterruptTrigger getMode();
}

class DetachInterruptMsg extends JArduinoProtocolPacket {
    InterruptPin getInterrupt();
}

class Eeprom_readMsg extends JArduinoProtocolPacket {
    short getAddress();
}

class Eeprom_writeMsg extends JArduinoProtocolPacket {
    short getAddress();
    byte getValue();
}

class Eeprom_sync_writeMsg extends JArduinoProtocolPacket {
    short getAddress();
    byte getValue();
}

class PingMsg extends JArduinoProtocolPacket;

// Result messages
class DigitalReadResultMsg extends JArduinoProtocolPacket {
    DigitalState getValue();
}

class AnalogReadResultMsg extends JArduinoProtocolPacket {
    short getValue();
}

class PulseInResultMsg extends JArduinoProtocolPacket {
    short getValue();
}

class PongMsg extends JArduinoProtocolPacket;

class InterruptNotificationMsg extends JArduinoProtocolPacket {
    InterruptPin getInterrupt();
}

class Eeprom_valueMsg extends JArduinoProtocolPacket {
    short getAddress();
    byte getValue();
}

class Eeprom_write_ackMsg extends JArduinoProtocolPacket {
    short getAddress();
}

Usage Examples

Basic Observer Implementation

import org.sintef.jarduino.observer.*;
import org.sintef.jarduino.*;

public class BasicArduinoObserver implements JArduinoObserver {
    @Override
    public void receiveMsg(byte[] msg) {
        // Parse incoming message
        FixedSizePacket packet = JArduinoProtocol.createMessageFromPacket(msg);

        // Handle different message types
        if (packet instanceof AnalogReadResultMsg) {
            AnalogReadResultMsg result = (AnalogReadResultMsg) packet;
            System.out.println("Analog reading: " + result.getValue());

        } else if (packet instanceof DigitalReadResultMsg) {
            DigitalReadResultMsg result = (DigitalReadResultMsg) packet;
            System.out.println("Digital state: " + result.getValue());

        } else if (packet instanceof PongMsg) {
            System.out.println("Arduino is alive (received pong)");

        } else if (packet instanceof InterruptNotificationMsg) {
            InterruptNotificationMsg notification = (InterruptNotificationMsg) packet;
            System.out.println("Interrupt triggered on: " + notification.getInterrupt());
        }
    }
}

Comprehensive Message Handler Implementation

import org.sintef.jarduino.msg.*;

public class ComprehensiveArduinoHandler extends JArduinoMessageHandler {
    @Override
    public void handleDigitalReadResult(DigitalReadResultMsg msg) {
        DigitalState state = msg.getValue();
        System.out.println("Digital pin read: " + state);

        // Respond to button press
        if (state == DigitalState.HIGH) {
            handleButtonPressed();
        }
    }

    @Override
    public void handleAnalogReadResult(AnalogReadResultMsg msg) {
        short value = msg.getValue();
        System.out.println("Analog reading: " + value);

        // Convert to voltage (assuming 5V reference)
        double voltage = (value / 1023.0) * 5.0;
        System.out.println("Voltage: " + voltage + "V");

        // Trigger actions based on sensor reading
        if (value > 512) {
            handleHighSensorValue();
        }
    }

    @Override
    public void handlePong(PongMsg msg) {
        System.out.println("Arduino connection confirmed");
        setConnectionStatus(true);
    }

    @Override
    public void handleInterruptNotification(InterruptNotificationMsg msg) {
        InterruptPin interrupt = msg.getInterrupt();
        System.out.println("External interrupt: " + interrupt);

        // Handle different interrupt sources
        switch (interrupt) {
            case PIN_2_INT0:
                handleEmergencyStop();
                break;
            case PIN_3_INT1:
                handleUserButton();
                break;
        }
    }

    @Override
    public void handleEeprom_value(Eeprom_valueMsg msg) {
        short address = msg.getAddress();
        byte value = msg.getValue();
        System.out.println("EEPROM[" + address + "] = " + value);

        // Store configuration values
        storeConfigValue(address, value);
    }

    @Override
    public void handleEeprom_write_ack(Eeprom_write_ackMsg msg) {
        short address = msg.getAddress();
        System.out.println("EEPROM write confirmed at address: " + address);
    }

    @Override
    public void handlePulseInResult(PulseInResultMsg msg) {
        short duration = msg.getValue();
        System.out.println("Pulse duration: " + duration + " microseconds");

        // Calculate distance from ultrasonic sensor
        double distance = (duration * 0.034) / 2.0; // cm
        System.out.println("Distance: " + distance + " cm");
    }

    // Helper methods
    private void handleButtonPressed() { /* ... */ }
    private void handleHighSensorValue() { /* ... */ }
    private void setConnectionStatus(boolean connected) { /* ... */ }
    private void handleEmergencyStop() { /* ... */ }
    private void handleUserButton() { /* ... */ }
    private void storeConfigValue(short address, byte value) { /* ... */ }
}

Observer Registration and Management

import org.sintef.jarduino.serial.Serial4JArduino;
import org.sintef.jarduino.observer.*;

public class ObserverManagement {
    private Serial4JArduino arduino;
    private List<JArduinoObserver> observers;

    public ObserverManagement(String port) {
        arduino = new Serial4JArduino(port);
        observers = new ArrayList<>();
    }

    public void setupObservers() {
        // Create different observers for different purposes
        JArduinoObserver sensorObserver = new SensorDataObserver();
        JArduinoObserver loggingObserver = new LoggingObserver();
        JArduinoObserver alertObserver = new AlertObserver();

        // Register all observers
        arduino.register(sensorObserver);
        arduino.register(loggingObserver);
        arduino.register(alertObserver);

        observers.add(sensorObserver);
        observers.add(loggingObserver);
        observers.add(alertObserver);
    }

    public void cleanup() {
        // Unregister all observers
        for (JArduinoObserver observer : observers) {
            arduino.unregister(observer);
        }
        observers.clear();
        arduino.close();
    }
}

Custom Message Processing Pipeline

public class MessageProcessingPipeline implements JArduinoObserver {
    private List<MessageProcessor> processors;

    public MessageProcessingPipeline() {
        processors = new ArrayList<>();
        processors.add(new MessageValidator());
        processors.add(new MessageLogger());
        processors.add(new MessageAnalyzer());
        processors.add(new MessageDispatcher());
    }

    @Override
    public void receiveMsg(byte[] msg) {
        FixedSizePacket packet = JArduinoProtocol.createMessageFromPacket(msg);

        // Process message through pipeline
        for (MessageProcessor processor : processors) {
            try {
                packet = processor.process(packet);
                if (packet == null) {
                    // Message was consumed by processor
                    break;
                }
            } catch (Exception e) {
                System.err.println("Error processing message: " + e.getMessage());
                break;
            }
        }
    }

    interface MessageProcessor {
        FixedSizePacket process(FixedSizePacket packet);
    }

    class MessageValidator implements MessageProcessor {
        @Override
        public FixedSizePacket process(FixedSizePacket packet) {
            // Validate message format and content
            if (packet == null || packet.getPacket().length == 0) {
                throw new IllegalArgumentException("Invalid message");
            }
            return packet;
        }
    }

    class MessageLogger implements MessageProcessor {
        @Override
        public FixedSizePacket process(FixedSizePacket packet) {
            System.out.println("[LOG] " + packet.toString());
            return packet;
        }
    }

    class MessageAnalyzer implements MessageProcessor {
        @Override
        public FixedSizePacket process(FixedSizePacket packet) {
            // Analyze message patterns, frequencies, etc.
            analyzeMessagePattern(packet);
            return packet;
        }

        private void analyzeMessagePattern(FixedSizePacket packet) {
            // Implementation for message analysis
        }
    }

    class MessageDispatcher implements MessageProcessor {
        @Override
        public FixedSizePacket process(FixedSizePacket packet) {
            // Dispatch to appropriate handlers based on message type
            if (packet instanceof AnalogReadResultMsg) {
                handleSensorData((AnalogReadResultMsg) packet);
            } else if (packet instanceof InterruptNotificationMsg) {
                handleInterrupt((InterruptNotificationMsg) packet);
            }
            return null; // Message consumed
        }

        private void handleSensorData(AnalogReadResultMsg msg) { /* ... */ }
        private void handleInterrupt(InterruptNotificationMsg msg) { /* ... */ }
    }
}

Message Flow Architecture

The message handling system follows a clear flow:

  1. Message Reception: Communication layer receives raw bytes
  2. Message Parsing: JArduinoProtocol.createMessageFromPacket() creates typed objects
  3. Observer Notification: All registered observers receive the message
  4. Type-based Handling: Observers use instanceof or implement IJArduinoMessageHandler
  5. Application Logic: Observers execute application-specific responses

Error Handling

The observer system provides several error handling mechanisms:

  • Message Validation: Invalid messages are detected during parsing
  • Exception Isolation: Observer exceptions don't affect other observers
  • Connection Monitoring: Observers can detect communication failures
  • Automatic Cleanup: Proper observer unregistration prevents memory leaks

Threading Considerations

  • Observer Callbacks: Called on communication thread (not UI thread)
  • Thread Safety: Observers should be thread-safe or use synchronization
  • UI Updates: Use appropriate threading mechanisms (SwingUtilities.invokeLater, etc.)
  • Blocking Operations: Avoid long-running operations in observer callbacks

Dependencies

  • JArduino Core: org.sintef.jarduino.core for protocol and message classes
  • Java Collections: java.util.* for observer management
  • Concurrency: java.util.concurrent.* for thread-safe implementations

Install with Tessl CLI

npx tessl i tessl/maven-org-sintef-jarduino--org-sintef-jarduino

docs

advanced-features.md

bluetooth-communication.md

core-protocol.md

gui-components.md

index.md

message-handling.md

serial-communication.md

tile.json