Napisać działający kod, w którym...:
Wątek Centralka nadzoruje pracę (wątków) czujników kontrolnych. Nadzorowanie to sprowadza się do:
sprawdzania stanu poszczególnych czujników i sygnalizowania sytuacji alarmowych (gdy średni stan czujników przekracza pewną zadaną wartość krytyczną) oraz
podłączania nowych czujników i wyłączania czujników pracujących - gdy nadejdzie takie żądanie z zewnątrz.
Wątek Sensor reprezentuje pewien czujnik monitorujący stan (np. temperaturę, odkształcenie, ...) jakiegoś urządzenia/elementu. Wartość liczbowa odczytanego stanu ma być przekazana do Centralki, która na tej podstawie podejmuje decyzję o włączeniu lub wyłączeniu alarmu. Można przyjąć, że liczba jednocześnie obsługiwanych czujników będzie ograniczona - np. nie większa niż 10.
Program główny poniżej ilustruje przykładowe operacje, jakie byłyby wykonywane przy pomocy Centralki. Kod programu głównego nie należy do rozwiązania zadania (ale z pewnością przyda się do testowania).
Sterowanie Centralką nie musi wcale odbywać się przy pomocy komunikatów (tak, jak jest w przykładzie). Musi jednak być jasno sprecyzowane, w jaki sposób program główny może dodać nowy Sensor, wyłączyć pracujący Sensor oraz zakończyć pracę Centralki. Sama Centralka musi właściwie reagować na takie wymuszenia z programu głównego, jak również utrzymywać komunikację z czujnikami i na tej podstawie właściwie sterować włączaniem/wyłączaniem alarmu. Sensory muszą właściwie współpracować z Centralką (w tym - kończyć pracę, gdy Centralka tego zażąda).
Rozwiązanie ma się znaleźć w katalogu nazwanym od swojego nazwiska. Niech w katalogu tym będą również wszystkie wykorzystywane moduły.
W rozwiązaniu warto/należy oprzeć się na poniższym kodzie (tzn. kod ten uzupełnić, i/lub zmodyfikować...) :
with Disp; --modul do wspolbieznego wyswietlania na ekranie + ew.inne pomocne moduly ...??...
procedure tresc is
--zmienne globalne ...??...
task type Sensor is -- + ewentualne obslugiwane komunikaty ...??...
end Sensor;
type Sensor_Ptr is access Sensor;
task Centralka is
entry Dodaj_Czujnik(nowy: in Sensor_Ptr); --dodawanie nowego czujnika do monitorowania
entry Zakoncz_Prace_Czujnika(cz: in Sensor_Ptr);
entry Zakoncz_Prace; --wylacza wszystkie czujniki i siebie + ew. inne wejscia ...??...
end Centralka;
task body Sensor is
stan: integer := 0;
begin
loop
-- ...??...
stan := (stan + 1117) mod 7 + 1; --"odczytywanie" stanu czujnika
delay(duration((stan+7)mod 7) / 50.0); --czas "zuzyty" na odczyt
--komunikacja z Centralka / ew. konczenie pracy Sensora / ... TRZEBA NAPISAC!!!
end loop;
end Sensor;
task body Centralka is
Sredni_Stan : Float := 0.0;
Alarm : Boolean := false;
begin
--funkcjonowanie Centralki nadzorujacej Sensory
-- (w tym wyznaczanie wartosci zmiennej Sredni_Stan) TRZEBA NAPISAC!!!
--alarmowanie wygladaloby jakos tak:
if Sredni_Stan > 3.0 then
Alarm := true;
Disp.Screen.Print("ALARM! Sredni stan = " & Float'Image(Sredni_Stan));
else
if Alarm then
Alarm := false;
Disp.Screen.Print("Koniec alarmu.");
end if;
end if;
-- ...??...
end Centralka;
pom1, pom2: Sensor_Ptr;
begin --program glowny zawiera przykladowe wywolania operacji sterujacych praca centralki:
Centralka.Dodaj_Czujnik(new Sensor); -- * dodawanie nowych czujnikow
pom1 := new Sensor; Centralka.Dodaj_Czujnik(pom1); delay 2.0;
Centralka.Dodaj_Czujnik(new Sensor);
pom2 := new Sensor; Centralka.Dodaj_Czujnik(pom2); delay 1.5;
Centralka.Zakoncz_Prace_Czujnika(pom2); delay 2.0; -- * wylaczenie dodanego wczesniej czujnika
Centralka.Dodaj_Czujnik(new Sensor); -- * znow dodanie czujnika
Centralka.Zakoncz_Prace_Czujnika(pom1); delay 5.0; -- * znow wylaczenie czujnika
Centralka.Zakoncz_Prace; -- * wylaczenie centralki (wraz ze wszystkimi czujnikami)
end tresc;
with Display;
use Display;--modul do wspolbieznego wyswietlania na ekranie
with Ada.Text_IO;
with Ada.Strings.Unbounded;
use Ada.Strings.Unbounded;
with Ada.Numerics.Float_Random;
use Ada.Numerics.Float_Random;
with Ada.Numerics.Discrete_Random;
procedure tresc is
--zmienne globalne ...??...
MAX_SENSOR : Integer := 10;
task type Sensor is -- + ewentualne obslugiwane komunikaty ...??...
entry pobiezWartosc (
-- pobiera wartosc odczytana przez sensor
wart : out Integer);
entry koniec; -- konczy prace sensora;
end Sensor;
type Sensor_Ptr is access Sensor;
task Centralka is
entry ustawStanAlarmowy (
s : in float);-- pozwala na zdefiniowanie progu wyzwalajacego alarm
entry Dodaj_Czujnik (
nowy : in Sensor_Ptr);--dodawanie nowego czujnika do monitorowania
entry Zakoncz_Prace_Czujnika (
cz : in Sensor_Ptr);
entry Zakoncz_Prace;--wylacza wszystkie czujniki i siebie + ew. inne wejscia ...??...
end Centralka;
task body Sensor is
stan : integer := 0;
koniec_czujnik : boolean := false;
begin
loop
-- ...??...
select
accept PobiezWartosc (
Wart : out Integer) do
--Screen.Write(To_Unbounded_String("czujnik"));
Wart := stan;
end PobiezWartosc;
or
accept koniec do
koniec_czujnik := true;
end koniec;
else
null;
end select;
if koniec_czujnik = true then
Screen.Write(To_Unbounded_String("koniec pracy czujnika"));
end if;
exit when koniec_czujnik = true;
stan := (stan + 1117) mod 7 + 1; --"odczytywanie" stanu czujnika
delay(duration((stan+7) mod 7) / 50.0); --czas "zuzyty" na odczyt
--komunikacja z Centralka / ew. konczenie pracy Sensora / ... TRZEBA NAPISAC!!!
end loop;
end Sensor;
task body Centralka is
stan_alarmowy : float := 3.0; -- domyslnie;
koniec : Boolean := false;
Sredni_Stan : Float := 0.0;
Alarm : Boolean := False;
Czujniki : array (1 .. MAX_SENSOR) of Sensor_Ptr := (others => null);
Czujniki_Slot : array (1 .. MAX_SENSOR) of Boolean := (others => false); -- zawiera informacje ktory "slot" w tablicy czujnikow jest wolny
-- jezeli ustawimy 10 czujnikow, usuniemy czujnik nr 5, to nastepny
nowy_czujnik : Sensor_Ptr := null; -- czujnik zostanie dodany na pozycje 5
koniec_czujnika : Sensor_Ptr := null;
liczba_czujnikow : Integer := 0;
i : Integer;
a : Integer := 0; -- sluzy do pobrania wartosci czujnika;
begin
Petla:
loop
select
accept ustawStanAlarmowy (
s : in float) do
stan_alarmowy := s;
end ustawStanAlarmowy;
or
accept Dodaj_Czujnik (
Nowy : in Sensor_Ptr) do
nowy_czujnik := Nowy;
end Dodaj_Czujnik;
or
accept Zakoncz_Prace_Czujnika (
cz : in Sensor_Ptr) do
koniec_czujnika := cz;
end Zakoncz_Prace_Czujnika;
else
null;
end select;
if koniec_czujnika /= null then
for i in 1..10 loop
if czujniki(i) = koniec_czujnika then
czujniki_slot(i) := false;
czujniki(i).koniec;
liczba_czujnikow := liczba_czujnikow - 1;
czujniki(i) := null;
Screen.Write(To_Unbounded_String("Liczba czujnikow: ") & Integer'Image(liczba_czujnikow));
exit;
end if;
end loop;
koniec_czujnika := null;
end if;
if Nowy_czujnik /= null and liczba_czujnikow < MAX_SENSOR then -- dodanie czujnika
for i in 1..10 loop -- szukanie miejsca w tabl na nowy czujnik
if czujniki_slot(i)= false then -- wolne miejsce
czujniki_slot(i) := true;
liczba_czujnikow := liczba_czujnikow + 1;
Czujniki(i) := nowy_czujnik;
Screen.Write(To_Unbounded_String("Liczba czujnikow: ") & Integer'Image(liczba_czujnikow));
exit;
end if;
end loop;
nowy_czujnik := null;
end if;
select
accept Zakoncz_Prace do-- zakonczenie pracy
Screen.Write(To_Unbounded_String("Centrala konczy prace"));
koniec := true;
end Zakoncz_Prace;
else
null;
end select;
if Koniec = True then
for i in 1..MAX_SENSOR loop
if czujniki(i) /= null then
czujniki(i).koniec;
end if;
end loop;
end if;
exit when Koniec = True;
--funkcjonowanie Centralki nadzorujacej Sensory
-- (w tym wyznaczanie wartosci zmiennej Sredni_Stan) TRZEBA NAPISAC!!!
sredni_stan := 0.0;
if liczba_czujnikow > 0 then
a := 0;
for i in 1..10 loop
if czujniki_slot(i) = true then
czujniki(i).pobiezWartosc(a);
sredni_stan := sredni_stan + Float(a);
end if;
end loop;
sredni_stan := sredni_stan / float(liczba_czujnikow);
end if;
Screen.Write(To_Unbounded_String("Sredni stan = ") & Float'Image(Sredni_Stan));
--alarmowanie wygladaloby jakos tak:
if Sredni_Stan > stan_alarmowy then
Alarm := true;
Screen.Write(To_Unbounded_String("ALARM! Sredni stan = ") & Float'Image(Sredni_Stan));
else
if Alarm then
Alarm := false;
Screen.Write(To_Unbounded_String("Koniec alarmu."));
end if;
end if;
end loop Petla;
-- ...??...
end Centralka;
pom1,
pom2 : Sensor_Ptr;
begin --program glowny zawiera przykladowe wywolania operacji sterujacych praca centralki:
Centralka.ustawStanAlarmowy(4.0);
Centralka.Dodaj_Czujnik(new Sensor); -- * dodawanie nowych czujnikow
pom1 := new Sensor;
Centralka.Dodaj_Czujnik(pom1);
delay 2.0;
Centralka.Dodaj_Czujnik(new Sensor);
pom2 := new Sensor;
Centralka.Dodaj_Czujnik(pom2);
delay 1.5;
Centralka.Zakoncz_Prace_Czujnika(pom2);
delay 2.0; -- * wylaczenie dodanego wczesniej czujnika
Centralka.Dodaj_Czujnik(new Sensor); -- * znow dodanie czujnika
Centralka.Zakoncz_Prace_Czujnika(pom1);
delay 5.0; -- * znow wylaczenie czujnika
Centralka.Zakoncz_Prace; -- * wylaczenie centralki (wraz ze wszystkimi czujnikami)
end tresc;
with Display; --modul do wspolbieznego wyswietlania na ekranie
with Ada.Strings.Unbounded;
procedure lab2 is
--zmienne globalne ...??...
N : constant Integer := 10; --liczba czujnikow - stala
task type Sensor is -- + ewentualne obslugiwane komunikaty ...??...
entry Koniec;
entry Odczytaj(wartosc: out Integer);
end Sensor;
type Sensor_Ptr is access Sensor;
SensorArray : array(1..N) of Sensor_Ptr;
task Centralka is
entry Dodaj_Czujnik(nowy: in Sensor_Ptr); --dodawanie nowego czujnika do monitorowania
entry Zakoncz_Prace_Czujnika(cz: in Sensor_Ptr);
entry Zakoncz_Prace; --wylacza wszystkie czujniki i siebie + ew. inne wejscia ...??...
end Centralka;
task body Sensor is
stan: integer := 0;
kill : Boolean :=false; --zmienna pomocnicza do konczenia zadania
begin
loop
stan := (stan + 1117) mod 7 + 1; --"odczytywanie" stanu czujnika
delay(duration((stan+7)mod 7) / 50.0); --czas "zuzyty" na odczyt
--komunikacja z Centralka / ew. konczenie pracy Sensora / ...
select
accept Koniec do
Display.Screen.Write(Ada.Strings.Unbounded.To_Unbounded_String("czujnik konczy"));
kill:=true;
end Koniec;
or
accept Odczytaj(wartosc: out Integer) do
Display.Screen.Write(Ada.Strings.Unbounded.To_Unbounded_String("odczyt z czujnika"));
wartosc := stan;
end Odczytaj;
or
delay(duration(0));
end select;
if kill = true then
exit; -- konczymy petle zadania
end if;
end loop;
end Sensor;
task body Centralka is
Sredni_Stan : Float := 0.0;
Alarm : Boolean := false;
n : Integer :=0; -- liczba czujnikow w centralce
i : Integer :=0; -- licznik petli
p : Integer :=0; -- zm pomocnicza
kill : Boolean :=false; --zmienna pomocnicza do konczenia zadania
begin
loop
--funkcjonowanie Centralki nadzorujacej Sensory
-- (w tym wyznaczanie wartosci zmiennej Sredni_Stan)
select
accept Dodaj_Czujnik(nowy: in Sensor_Ptr) do
if n <= N then
n:=n+1;
SensorArray(n):=nowy;
--Display.Screen.Write(Ada.Strings.Unbounded.To_Unbounded_String("dodaje."));
end if;
end Dodaj_Czujnik;
or
accept Zakoncz_Prace_Czujnika(cz: in Sensor_Ptr) do
--Display.Screen.Write(Ada.Strings.Unbounded.To_Unbounded_String("koncze prace czujnika"));
cz.Koniec;
for i in 1..n loop
if SensorArray(i) = cz then
if i < n then
SensorArray(i) := SensorArray(n);
end if;
SensorArray(i):= null;
exit;
end if;
end loop;
n:=n-1;
--Display.Screen.Write(Ada.Strings.Unbounded.To_Unbounded_String("zakonczylem prace czujnika"));
end Zakoncz_Prace_Czujnika;
or
accept Zakoncz_Prace do
--Display.Screen.Write(Ada.Strings.Unbounded.To_Unbounded_String("rozpoczynam procedure zamykania centralki"));
kill:=true;
for i in 1..n loop
SensorArray(i).Koniec;
end loop;
--Display.Screen.Write(Ada.Strings.Unbounded.To_Unbounded_String("koncze procedure zamykania centralki"));
end Zakoncz_Prace;
or
delay(duration(0));
end select;
if kill = false then
--obliczanie stanu sredniego
for i in 1..n loop
SensorArray(i).Odczytaj(p);
Sredni_Stan:=float(Sredni_Stan)+float(p);
end loop;
Sredni_Stan:=float(Sredni_Stan)/float(n);
--alarmowanie wygladaloby jakos tak:
if Sredni_Stan > 3.0 then
Alarm := true;
Display.Screen.Write(Ada.Strings.Unbounded.To_Unbounded_String("ALARM! Sredni stan = " & Float'Image(Sredni_Stan)));
else
if Alarm then
Alarm := false;
Display.Screen.Write(Ada.Strings.Unbounded.To_Unbounded_String("Koniec alarmu."));
end if;
end if;
delay(duration(0));
else
exit;
end if;
end loop;
end Centralka;
pom1, pom2: Sensor_Ptr;
begin --program glowny zawiera przykladowe wywolania operacji sterujacych praca centralki:
Centralka.Dodaj_Czujnik(new Sensor); -- * dodawanie nowych czujnikow
pom1 := new Sensor; Centralka.Dodaj_Czujnik(pom1); delay 2.0;
Centralka.Dodaj_Czujnik(new Sensor);
pom2 := new Sensor; Centralka.Dodaj_Czujnik(pom2); delay 1.5;
Centralka.Zakoncz_Prace_Czujnika(pom2); delay 2.0; -- * wylaczenie dodanego wczesniej czujnika
Centralka.Dodaj_Czujnik(new Sensor); -- * znow dodanie czujnika
Centralka.Zakoncz_Prace_Czujnika(pom1); delay 5.0; -- * znow wylaczenie czujnika
Centralka.Zakoncz_Prace; -- * wylaczenie centralki (wraz ze wszystkimi czujnikami)
end lab2;