Este artigo apresenta de maneira didática e prática o uso do Ollama, uma ferramenta de código aberto para criação e gerenciamento de modelos de inteligência artificial generativa, integrada com Python em um computador de borda. Este computador é capaz de interagir via Bluetooth com uma placa Nucleo-WB09KE, para coleta e transmissão de dados provenientes de sensores em tempo real. Como exemplo prático, abordaremos a leitura e envio de dados de um sensor DHT22, como temperatura e umidade, usando padrões de projeto reconhecidos na literatura de sistemas embarcados e tempo real.
Para garantir clareza e robustez no código, utilizaremos os padrões de projeto Proxy e Observer/Listener, baseados em referências consagradas como os livros “Design Patterns for Embedded Systems in C” e “Real-Time Design Patterns”, ambos de Bruce Powel Douglass. O padrão Proxy será empregado para encapsular adequadamente o acesso ao hardware específico, enquanto o Observer será utilizado para gerenciar a comunicação de eventos e mudanças de estado entre as tarefas de firmware e o computador de borda. O artigo também detalhará como converter o texto gerado pelo Ollama em áudio para reprodução via alto-falantes, criando uma experiência interativa e amigável para o usuário final.
Problema a ser Resolvido
No desenvolvimento de sistemas embarcados integrados com inteligência artificial generativa, frequentemente encontramos desafios relacionados à complexidade da interação entre diferentes componentes, tais como microcontroladores, sensores, computadores de borda e interfaces de usuário. Um problema comum é a falta de organização estrutural, clareza e facilidade de manutenção do código, especialmente quando se integra diferentes tecnologias como comunicação sem fio, processamento local de dados e feedback em áudio para usuários.
No cenário proposto, precisamos resolver alguns desafios específicos: um computador de borda equipado com Ollama deve se comunicar via Bluetooth com uma placa STM32 Nucleo-WB09KE, que coleta informações ambientais através de um sensor DHT22 (temperatura e umidade). Esses dados precisam ser acessados de maneira confiável e rápida pelo computador de borda, que por sua vez irá gerar mensagens compreensíveis para o usuário e convertê-las em áudio para reprodução em alto-falantes. Além disso, o computador de borda deve interagir com o usuário de forma amigável, cumprimentando-o ao iniciar o sistema e despedindo-se quando o software for encerrado.
Outro aspecto importante é a necessidade de uma arquitetura robusta e escalável, capaz de acomodar futuros sensores adicionais, novos algoritmos de IA e outras formas de interação sem causar grandes alterações no código-fonte ou afetar o desempenho e a estabilidade do sistema. Além disso, existe a necessidade de manter separação clara das responsabilidades entre as diferentes partes do sistema (firmware, hardware, software de IA e interface com o usuário), facilitando testes unitários e garantindo fácil manutenção e expansão futura.
Para solucionar esses problemas de forma estruturada e eficaz, adotaremos padrões de projeto conhecidos da literatura especializada. O padrão Proxy será utilizado para encapsular o acesso ao sensor DHT22 e à comunicação Bluetooth, permitindo a transparência no acesso ao hardware e a troca futura dos periféricos sem necessidade de alterar o restante do sistema. Já o padrão Observer/Listener ajudará na comunicação assíncrona, notificando eficientemente o computador de borda sobre novos dados recebidos ou mudanças de estado relevantes ocorridas na placa STM32.
Estrutura do Padrão
Neste projeto, utilizaremos dois padrões essenciais: Proxy e Observer/Listener. Cada um tem funções específicas e complementares para garantir a eficiência, robustez e manutenção simplificada do sistema proposto. A seguir detalhamos a estrutura de cada padrão e como eles serão utilizados para resolver os desafios apresentados.
1. Estrutura do Padrão Proxy
O padrão Proxy é utilizado para controlar e encapsular o acesso a recursos externos ou internos do sistema, como sensores e interfaces de comunicação. Sua estrutura típica é composta por:
- Subject (Interface ou Classe Abstrata): Define a interface que será implementada tanto pelo objeto real quanto pelo proxy.
- RealSubject: Classe concreta que realiza o acesso direto ao hardware ou recurso (por exemplo, leitura direta do sensor DHT22).
- Proxy: Classe intermediária que encapsula e controla o acesso ao objeto real, adicionando funcionalidades extras, tais como verificação de acesso, conversão de formatos ou gerenciamento de comunicação.
Aplicado ao nosso contexto, teremos uma classe Proxy chamada SensorProxy
, que implementa a interface abstrata SensorInterface
, com operações básicas como getTemperature()
e getHumidity()
. Essas operações internas serão delegadas à classe DHT22Sensor
, que representa o objeto real (RealSubject).
Exemplo simplificado em C:
/* Interface abstrata do sensor */
typedef struct {
float (*getTemperature)(void);
float (*getHumidity)(void);
} SensorInterface;
/* Implementação RealSubject: Sensor DHT22 */
float DHT22_getTemperature(void);
float DHT22_getHumidity(void);
SensorInterface DHT22Sensor = {
.getTemperature = DHT22_getTemperature,
.getHumidity = DHT22_getHumidity
};
/* Proxy para encapsulamento de acesso */
float SensorProxy_getTemperature(void);
float SensorProxy_getHumidity(void);
SensorInterface SensorProxy = {
.getTemperature = SensorProxy_getTemperature,
.getHumidity = SensorProxy_getHumidity
};
No proxy, é possível adicionar verificação de erros, conversão de unidades, ou mesmo comunicação remota via Bluetooth com o computador de borda.
2. Estrutura do Padrão Observer/Listener
O padrão Observer/Listener permite que um objeto (Subject) notifique outros objetos (Observers ou Listeners) automaticamente sobre mudanças de estado ou novos eventos ocorridos, facilitando comunicação assíncrona. Sua estrutura básica envolve:
- Subject: Mantém uma lista de observadores e notifica-os sobre mudanças.
- Observer (Listener): Define uma interface para objetos interessados em receber notificações sobre eventos.
No nosso projeto, o firmware no STM32 usará o padrão Observer para notificar o computador de borda sempre que novos dados forem coletados do sensor DHT22. O computador de borda atua como Observer, recebendo notificações periódicas do firmware (Subject).
Exemplo simplificado em C no firmware da placa Nucleo-WB09KE:
/* Interface Listener para notificação de dados do sensor */
typedef void (*SensorListener)(float temperature, float humidity);
/* Subject: SensorDataNotifier */
#define MAX_LISTENERS 5
SensorListener listeners[MAX_LISTENERS];
int num_listeners = 0;
void registerListener(SensorListener listener) {
if (num_listeners < MAX_LISTENERS) {
listeners[num_listeners++] = listener;
}
}
void notifyListeners(float temperature, float humidity) {
for (int i = 0; i < num_listeners; i++) {
listeners[i](temperature, humidity);
}
}
/* Exemplo de chamada após leitura do sensor */
void sensorReadingTask(void) {
float temp = DHT22_getTemperature();
float hum = DHT22_getHumidity();
notifyListeners(temp, hum);
}
O computador de borda atuará como Observer, registrando-se no firmware como Listener e recebendo notificações periódicas dos dados atualizados.
Integração com Ollama e Processamento de Áudio (Computador de Borda)
No computador de borda, Python integrará Ollama para gerar texto interativo, que será convertido em áudio para reprodução. Uma estrutura simplificada é:
- Gerador Ollama: Processa dados recebidos do STM32 e gera mensagens interativas.
- Conversor Texto-para-Fala: Converte o texto gerado em áudio.
Exemplo simplificado em Python:
import ollama
import pyttsx3
def gerar_mensagem(temperatura, umidade):
prompt = f"Informe ao usuário a temperatura de {temperatura} graus Celsius e a umidade de {umidade}%."
response = ollama.chat(model='llama3', messages=[{'role': 'user', 'content': prompt}])
return response['message']['content']
def reproduzir_audio(texto):
engine = pyttsx3.init()
engine.say(texto)
engine.runAndWait()
# Callback recebendo dados via Bluetooth
def dados_recebidos(temperatura, umidade):
texto = gerar_mensagem(temperatura, umidade)
reproduzir_audio(texto)
# Exemplo de inicialização do Listener (Observer)
registrar_listener_bluetooth(dados_recebidos)
# Mensagens ao iniciar e sair do software
reproduzir_audio("Bem-vindo ao sistema inteligente.")
# Ao sair:
reproduzir_audio("Obrigado por utilizar nosso sistema. Até breve.")
Essa estrutura claramente organizada e dividida entre padrões Proxy e Observer permitirá um desenvolvimento eficiente, fácil manutenção e excelente escalabilidade para expansão futura.
Papéis de Colaboração (Collaborations Roles)
Os padrões Proxy e Observer/Listener utilizados no projeto possuem papéis bem definidos que desempenham funções específicas para promover clareza, escalabilidade e manutenção simplificada do sistema. Vamos detalhar os papéis envolvidos nestes padrões, destacando a interação entre eles e como se aplicam na prática ao nosso sistema.
Papéis do Padrão Proxy
- SensorInterface (Subject):
É uma interface abstrata que define a forma padrão de acesso aos dados do sensor, garantindo que tanto o objeto real quanto o proxy ofereçam as mesmas operações. Esta interface garante transparência ao cliente do sensor, independentemente do mecanismo ou hardware específico utilizado. - DHT22Sensor (RealSubject):
Classe concreta que implementa diretamente as operações definidas pelaSensorInterface
. É responsável pela comunicação física com o sensor DHT22, realizando leituras reais de temperatura e umidade. - SensorProxy (Proxy):
Classe intermediária que implementa a mesma interface (SensorInterface
) e atua como um controlador do acesso ao sensor. Esta classe pode adicionar funcionalidades importantes, tais como a validação dos dados, conversão de unidades, comunicação remota (via Bluetooth), e gerenciamento de erros. Dessa forma, o Proxy permite alterar facilmente o objeto real sem afetar o restante do sistema. - SensorClient (Cliente):
Cliente que utiliza a interface fornecida pelo Proxy para acessar os dados do sensor, sem precisar se preocupar com detalhes específicos do hardware ou das comunicações envolvidas.
Papéis do Padrão Observer/Listener
- Subject (SensorDataNotifier):
Mantém uma lista de objetos interessados (listeners ou observadores) e notifica-os automaticamente sempre que um novo evento ocorre, como uma nova leitura dos dados do sensor. Gerencia o registro e remoção de observadores e dispara notificações apropriadas para os observadores registrados. - Observer (Listener / BluetoothListener):
Interface que define um callback (função de retorno), utilizada por qualquer objeto que deseja receber notificações automáticas de eventos específicos. No nosso contexto, o computador de borda desempenha esse papel ao registrar-se como Listener para ser informado sempre que novos dados ambientais forem coletados pelo STM32. - ConcreteObserver (Computador de Borda):
Implementa a interface Observer. No contexto deste projeto, ele utiliza os dados recebidos para alimentar o Ollama, gerando mensagens interativas e transformando-as em áudio para o usuário. Desta forma, o ConcreteObserver está diretamente ligado às funcionalidades de processamento de IA generativa e reprodução de áudio. - Event:
Classe representando os eventos enviados pelo Subject para os Observers. No exemplo do projeto, os eventos contêm dados ambientais (temperatura e umidade) coletados periodicamente pelo firmware do STM32.
Papéis Adicionais (Micro-padrões para Expansões Futuras):
Para promover escalabilidade e fácil manutenção, podemos ainda destacar alguns papéis adicionais que podem emergir futuramente:
- DataValidator (Micro-padrão Validator):
Responsável pela validação e verificação dos dados coletados, evitando erros e garantindo integridade das informações. - BluetoothGateway (Micro-padrão Gateway):
Responsável por encapsular completamente a comunicação Bluetooth, facilitando a adição de outros protocolos ou métodos de comunicação no futuro. - AudioSynthesizer (Micro-padrão Façade):
Uma interface simplificada que abstrai as operações complexas relacionadas à geração de áudio a partir de texto, permitindo futuramente a utilização de diferentes mecanismos de síntese sem impacto nos demais componentes. - AIChatProcessor (Micro-padrão Strategy):
Abstração que permite a integração simplificada de diferentes modelos generativos, tais como modelos locais ou remotos, sem alterar o código que depende diretamente do mecanismo de geração de mensagens.
Esses papéis são propostos para tornar o sistema mais flexível, expansível e modular, podendo evoluir para atender a novas demandas sem gerar impacto negativo no código já implementado.
Consequências
A utilização dos padrões Proxy e Observer/Listener, bem como os micro-padrões sugeridos, traz vantagens significativas e algumas consequências importantes que precisam ser consideradas no desenvolvimento do sistema embarcado integrado com inteligência generativa (Ollama). A seguir, detalhamos as principais consequências observadas ao adotar essa abordagem de projeto estruturada.
Consequências Positivas:
1. Clareza e Manutenção Simplificada:
O uso do padrão Proxy simplifica o código ao encapsular a interação direta com o sensor e hardware. Alterações futuras no hardware, sensores ou protocolos são isoladas no Proxy, não afetando o restante do sistema, o que reduz o esforço de manutenção.
2. Reutilização e Portabilidade:
Ao definir interfaces claras e bem abstraídas para acesso aos dados (por meio de Proxy e Observer), o sistema ganha em portabilidade. Assim, é possível reutilizar facilmente módulos como sensores ou comunicação sem necessidade de alterações profundas no código.
3. Comunicação Eficiente e Assíncrona:
O padrão Observer garante notificações imediatas e eficientes ao computador de borda sobre novos dados recebidos do firmware, evitando consultas constantes (polling) que poderiam gerar sobrecarga no sistema e desperdício de recursos computacionais.
4. Facilidade de Expansão e Escalabilidade:
Ao adotar micro-padrões como Validator, Gateway, Façade e Strategy, a adição de novos componentes, sensores, modelos de IA e interfaces de comunicação pode ser feita rapidamente. A arquitetura modular permite integrar facilmente novas funcionalidades sem grandes refatorações.
5. Robustez e Confiabilidade:
Padrões de projeto estabelecem estruturas testadas e validadas pela comunidade. A utilização desses padrões contribui diretamente para maior robustez e confiabilidade do sistema, além de reduzir riscos associados ao desenvolvimento customizado e não estruturado.
6. Melhor Experiência para o Usuário:
A integração com Ollama e o feedback em áudio melhoram significativamente a experiência do usuário final, proporcionando interações naturais e compreensíveis, com informações claramente apresentadas.
Consequências Negativas e Pontos de Atenção:
1. Complexidade Inicial:
O uso desses padrões, embora beneficie significativamente a manutenção e escalabilidade do sistema, pode introduzir complexidade adicional no estágio inicial do projeto. Para equipes menores ou menos experientes, pode ser necessário um período de aprendizado ou adaptação para a correta aplicação dos padrões.
2. Sobrecarga de Memória e Processamento:
Em sistemas embarcados com restrições severas de recursos, padrões como Proxy e Observer podem introduzir pequena sobrecarga devido às camadas adicionais de abstração e à necessidade de armazenamento e gerenciamento das listas de observadores.
3. Latência em Comunicação:
Embora o padrão Observer evite o polling contínuo, ainda existe um tempo associado à notificação e processamento dos eventos. Se não implementado corretamente, pode haver um leve aumento na latência do sistema. É importante planejar adequadamente a arquitetura e avaliar se essa latência é aceitável no contexto da aplicação.
4. Potencial Coupling Excessivo:
Se os papéis definidos pelos padrões não forem corretamente isolados, o sistema pode sofrer acoplamento excessivo entre os componentes, prejudicando a modularidade e dificultando futuras expansões ou manutenções. A implementação rigorosa dos papéis definidos é essencial para evitar esse problema.
Estratégias para Mitigar Consequências Negativas:
Para reduzir os pontos negativos e maximizar os benefícios, sugerimos algumas estratégias práticas:
- Realizar treinamentos específicos sobre padrões de projeto para a equipe envolvida, garantindo compreensão clara dos conceitos e implementações.
- Avaliar previamente a capacidade computacional da plataforma embarcada e otimizar a implementação dos padrões sempre que possível, para garantir que a sobrecarga seja mínima.
- Fazer testes de desempenho regulares, especialmente sobre comunicação e notificações, monitorando latência e ajustando parâmetros do sistema conforme necessário.
- Aplicar testes unitários rigorosos e revisões de código frequentes, garantindo que cada componente cumpra estritamente seu papel definido pelos padrões.
Ao considerar esses pontos com atenção, os padrões Proxy e Observer, aliados aos micro-padrões complementares sugeridos, oferecem uma solução robusta, flexível e sustentável para a integração de inteligência artificial generativa com sistemas embarcados e IoT.
Estratégias de Implementação
Para que a implementação dos padrões Proxy e Observer no projeto com Ollama, computador de borda e STM32 Nucleo-WB09KE seja eficaz e sem complicações, recomendamos estratégias claras, baseadas nas melhores práticas da engenharia de software embarcado. A seguir detalhamos estas estratégias, destacando o passo a passo recomendado para a implementação prática e bem-sucedida dos padrões e integrações sugeridos.
1. Implementação Gradual e Incremental
Uma abordagem incremental é recomendada ao implementar padrões complexos:
- Comece pelo Padrão Proxy, encapsulando o acesso ao sensor DHT22. Inicialmente, implemente e valide a comunicação direta com o hardware. Só após confirmação da funcionalidade básica, adicione a camada Proxy com funcionalidades adicionais como validação de dados e comunicação Bluetooth.
- Em seguida, implemente o Padrão Observer, registrando inicialmente um único observer simples que imprime os dados recebidos. Após validação, adicione o observer real, que é o computador de borda utilizando o Ollama.
2. Definição Clara de Interfaces
Interfaces bem definidas são a base da implementação robusta dos padrões de projeto:
- Utilize arquivos
.h
separados para interfaces (abstratas), mantendo-as bem documentadas com comentários explicativos. A utilização de interfaces abstratas facilita testes unitários e permite mudanças de implementação sem impacto nos usuários dessas interfaces.
Exemplo de interface clara em C:
// SensorInterface.h
#ifndef SENSOR_INTERFACE_H
#define SENSOR_INTERFACE_H
/**
* Obtém a temperatura atual em graus Celsius.
* @return Temperatura em Celsius.
*/
float getTemperature(void);
/**
* Obtém a umidade atual em percentual (%).
* @return Umidade relativa (%).
*/
float getHumidity(void);
#endif
3. Encapsulamento Rigoroso das Camadas
Separe claramente as camadas de firmware, comunicação, processamento de IA, e interface com o usuário:
- O firmware no STM32 não deve ter conhecimento dos detalhes internos do Ollama ou da síntese de voz. Seu papel limita-se a leitura dos sensores e notificação dos eventos.
- O computador de borda não precisa saber detalhes específicos do firmware ou do sensor, apenas espera notificações padronizadas.
Exemplo de organização sugerida:
Projeto/
├── firmware/
│ ├── drivers/ # Código para acesso ao DHT22
│ ├── proxy/ # Implementação Proxy
│ ├── observer/ # Implementação Observer
│ └── bluetooth/ # Comunicação Bluetooth
└── edge_computer/
├── ollama/ # Processamento de IA
├── audio/ # Conversão texto-áudio
├── listener/ # Observer Listener Bluetooth
└── main.py # Aplicação principal
4. Implementação da Comunicação Bluetooth Robusta
A comunicação via Bluetooth é um ponto sensível; sugerimos:
- Definir claramente protocolos de comunicação (formato JSON ou outro padrão leve), com validação de pacotes enviados e recebidos.
- Implementar rotinas robustas de reconexão automática em caso de perda temporária de comunicação.
Exemplo básico em formato JSON para envio do sensor:
{
"sensor": "DHT22",
"temperature": 25.3,
"humidity": 55.4,
"timestamp": 1713374823
}
5. Integração com Ollama e Processamento de Áudio
- A interface Python que integra o Ollama deve ser desacoplada do sistema Bluetooth através de callbacks ou listeners assíncronos, conforme definido pelo padrão Observer.
- Use bibliotecas maduras e bem testadas para conversão texto-áudio (e.g.,
pyttsx3
,gTTS
) visando robustez e desempenho.
Exemplo prático de integração em Python:
import ollama
import pyttsx3
class AIProcessor:
def __init__(self, model='llama3'):
self.model = model
self.engine = pyttsx3.init()
def generate_message(self, temp, hum):
prompt = f"A temperatura atual é de {temp} graus Celsius e a umidade relativa é {hum}%. Informe isso ao usuário de forma amigável."
response = ollama.chat(
model=self.model,
messages=[{'role': 'user', 'content': prompt}]
)
return response['message']['content']
def speak(self, message):
self.engine.say(message)
self.engine.runAndWait()
# Listener recebendo dados do Bluetooth
def on_sensor_data_received(data):
ai_processor = AIProcessor()
message = ai_processor.generate_message(data['temperature'], data['humidity'])
ai_processor.speak(message)
6. Validação e Testes Unitários
- Testes unitários para cada camada e padrão são essenciais. Garanta testes automatizados usando frameworks adequados, como Unity ou Ceedling em C, e pytest ou unittest em Python.
- Testes de integração entre firmware e computador de borda devem simular situações reais de operação, incluindo casos extremos (alta frequência de eventos, desconexões intermitentes, valores inválidos etc.).
7. Tratamento Cuidadoso das Exceções
Implemente rotinas para capturar e lidar com exceções tanto no firmware quanto no computador de borda, garantindo que o sistema nunca fique em um estado inconsistente ou imprevisível.
Exemplo de tratamento básico em Python:
try:
message = ai_processor.generate_message(temp, hum)
except Exception as e:
message = "Desculpe, ocorreu um problema ao gerar a mensagem."
print(f"Erro ao gerar mensagem: {e}")
ai_processor.speak(message)
Seguindo essas estratégias, a implementação dos padrões Proxy e Observer/Listener no projeto será mais robusta, clara, escalável e de fácil manutenção. Essas estratégias também aumentam a qualidade e confiabilidade do sistema final.
Modelo de Amostragem
Neste modelo de amostragem, apresentaremos um exemplo completo e integrado, ilustrando claramente como aplicar os padrões Proxy e Observer/Listener, além da integração com Ollama no computador de borda, para a comunicação via Bluetooth com uma placa STM32 Nucleo-WB09KE lendo dados do sensor DHT22.
Este exemplo prático permitirá compreender claramente as interações entre os componentes e validar a eficácia dos padrões utilizados.
Estrutura Geral do Sistema
O sistema completo pode ser resumido na seguinte estrutura de comunicação e processamento:
- STM32 Nucleo-WB09KE (Firmware em C)
- Proxy para encapsular a leitura do sensor DHT22.
- Observer (Listener) para notificar automaticamente o computador de borda via Bluetooth.
- Computador de Borda (Python com Ollama e conversor de áudio)
- Observer (Listener) recebendo notificações Bluetooth.
- Ollama gerando mensagens interativas com base nos dados do sensor.
- Sistema de áudio reproduzindo as mensagens geradas para o usuário.
Código Exemplo Simplificado (Firmware STM32 em C)
Interface Sensor (SensorInterface.h)
#ifndef SENSOR_INTERFACE_H
#define SENSOR_INTERFACE_H
float getTemperature(void);
float getHumidity(void);
#endif
RealSubject (DHT22Sensor.c)
#include "SensorInterface.h"
float getTemperature(void) {
// código real para leitura do sensor DHT22
return DHT22_read_temperature();
}
float getHumidity(void) {
return DHT22_read_humidity();
}
Proxy (SensorProxy.c)
#include "SensorInterface.h"
float getTemperature(void) {
float temp = DHT22_read_temperature();
return (temp > -40 && temp < 80) ? temp : -999.0; // Validação básica
}
float getHumidity(void) {
float hum = DHT22_read_humidity();
return (hum >= 0 && hum <= 100) ? hum : -999.0; // Validação básica
}
Observer (BluetoothNotifier.c)
#include "BluetoothNotifier.h"
#include "SensorInterface.h"
#include <stdio.h>
void notifySensorData(void) {
float temp = getTemperature();
float hum = getHumidity();
char json[128];
sprintf(json, "{\"temperature\":%.2f,\"humidity\":%.2f}", temp, hum);
Bluetooth_Send(json);
}
// Esta função é chamada por um timer (por exemplo, a cada 1 segundo)
void periodicSensorTask(void) {
notifySensorData();
}
Código Exemplo Simplificado (Computador de Borda Python com Ollama)
listener.py (Observer Bluetooth)
import bluetooth
import json
from ai_processor import AIProcessor
def listen_for_sensor_data():
ai_processor = AIProcessor()
socket = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
socket.connect(('xx:xx:xx:xx:xx:xx', 1))
try:
while True:
data = socket.recv(1024)
sensor_data = json.loads(data.decode('utf-8'))
temp = sensor_data['temperature']
hum = sensor_data['humidity']
ai_processor.process_and_speak(temp, hum)
except Exception as e:
print("Erro na comunicação Bluetooth:", e)
finally:
socket.close()
if __name__ == "__main__":
print("Bem-vindo ao sistema inteligente.")
listen_for_sensor_data()
ai_processor.py (Integração Ollama e áudio)
import ollama
import pyttsx3
class AIProcessor:
def __init__(self, model='llama3'):
self.model = model
self.engine = pyttsx3.init()
def generate_message(self, temp, hum):
prompt = f"Crie uma mensagem amigável informando a temperatura de {temp:.1f} graus Celsius e a umidade de {hum:.1f}%."
response = ollama.chat(
model=self.model,
messages=[{'role': 'user', 'content': prompt}]
)
return response['message']['content']
def process_and_speak(self, temp, hum):
if temp == -999.0 or hum == -999.0:
message = "Não foi possível obter uma leitura válida do sensor. Por favor, verifique o dispositivo."
else:
message = self.generate_message(temp, hum)
print("Mensagem gerada:", message)
self.engine.say(message)
self.engine.runAndWait()
def close_system(self):
self.engine.say("Obrigado por utilizar nosso sistema. Até breve.")
self.engine.runAndWait()
Testes do Sistema Completo
Para validar a implementação, sugerimos as seguintes etapas práticas de teste:
- Teste isolado do Proxy:
Validar leituras corretas do sensor, com valores esperados e tratamento adequado dos valores inválidos. - Teste do Observer Bluetooth:
Validar a comunicação Bluetooth estável e correta, incluindo reconexões automáticas. - Teste integrado com Ollama:
Verificar geração correta e clara das mensagens e reprodução adequada dos áudios. - Testes de exceção e robustez:
Realizar testes com desconexões propositais do Bluetooth, falhas do sensor e falhas do Ollama, garantindo comportamento previsível e seguro.
Resultados Esperados
Com este modelo de amostragem completo e funcional, esperamos obter:
- Comunicação robusta e transparente entre sensor, firmware e computador de borda.
- Mensagens amigáveis e naturais ao usuário final.
- Arquitetura modular e expansível, com capacidade fácil de incorporar novos sensores ou funcionalidades adicionais no futuro.
Esse exemplo prático oferece um modelo para validação e ponto de partida para a evolução contínua do sistema embarcado integrado com inteligência generativa.