Autor Beitrag
jeng
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 30



BeitragVerfasst: Sa 27.06.15 15:05 
Hallo Community,

Habe folgendes Problem.

Ich habe ein 8 Port Relais das meine Lampen steuern Soll.
Nun, also 8 mal on oder off.

Ich brauche also eine Funktion die mir sagt ob ein Licht schon an ist.
Hab mir ein arry [0..7] of integer erstellt.
Wie kann ich das array nun prüfen ob darin nun zb. port[4] 1 oder 0 ist.

Das problem ist, wenn port1 on ist also 1 im array steht, und ich port2 auch auf 1 schalte, dann port2 ausschalte muss ich prüfen was von dem array auf 1 steht und nur den gewählten port auf 0 schalten.


Zuletzt bearbeitet von jeng am So 28.06.15 10:22, insgesamt 1-mal bearbeitet
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Sa 27.06.15 15:34 
- Nachträglich durch die Entwickler-Ecke gelöscht -
GuaAck
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 376
Erhaltene Danke: 32

Windows 8.1
Delphi 10.4 Comm. Edition
BeitragVerfasst: Sa 27.06.15 19:19 
Hallo,

oft kann nur auf 8, 16 oder 32 binäre Port parallel zugeriffen werden, das hängt von der Hardware ab. Bei 8 Ports ist die Abbildung auf die 8 Bits eines Bytes sinnvoll.

Dann hat man üblicherweise ein Abbild der Zustände der Ports (als ein Byte) im Rechner oder liest sich dieses Abbild kurz vor einer Ausgabe ein. Ein OR mit $02 (=Binär 00000010) setzt Port 1 (wenn Port 0 das LSB ist) und ein AND mit $FD (=Binär 11111101) löscht Port 1. Abschließend muss das Abbild-Byte natürlich wieder an den Port ausgegeben werden (write o. ä.).

Mann sollte vermeiden, das zwei parallele Programmteile auf die gleiche Portgruppe zugreifen, dann gibt es natürlich Murks.

Viele Grüße
GuaAck
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Sa 27.06.15 22:50 
Hier kannst Du 32 BIT-Zustände prüfen:
www.swissdelphicente...showcode.php?id=1341
Xion
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
EE-Maler
Beiträge: 1952
Erhaltene Danke: 128

Windows XP
Delphi (2005, SmartInspect), SQL, Lua, Java (Eclipse), C++ (Visual Studio 2010, Qt Creator), Python (Blender), Prolog (SWIProlog), Haskell (ghci)
BeitragVerfasst: So 28.06.15 00:17 
Du kannst übrigens in Delphi auch inlined Assembler benutzen, was für hardwarenahe Anwendungen besonders schick ist.

www.delphipraxis.net...eiger-crashkurs.html

Das könnte z.B. so aussehen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
procedure SwitchLightOff( lightID: integer {0..31});
asm
  {lightID in EAX}
  MOV EDX, $FFFFFFFE
  ROL EDX, EAX
  AND PortMask, EDX
  OUT PortMask, PortID  
end;


Etwas Vorsicht ist bei Verwendung der Register notwendig, da logischerweise der Parameter und der Self-Pointer bei einem Objekt zum Zeitpunkt des Aufrufs mit Assembler in einem Register stehen müssen und außerdem nur die Register EAX,ECX und EDX durch die Funktion verändert werden dürfen.

_________________
a broken heart is like a broken window - it'll never heal
In einem gut regierten Land ist Armut eine Schande, in einem schlecht regierten Reichtum. (Konfuzius)
mandras
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 429
Erhaltene Danke: 107

Win 10
Delphi 6 Prof, Delphi 10.4 Prof
BeitragVerfasst: So 28.06.15 00:58 
Ist es nicht voreilig so viele Tips zu geben, bevor
die eigentliche Frage/Problematik nicht näher ausgeführt wurde?
jeng Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 30



BeitragVerfasst: So 28.06.15 11:19 
Hallo,

Also ich Danke euch für die vielen Gedanken Anstösse.

Ich bin nun ein bischen erschlagen von den Lösungsansätzen da ich Anfäger bin..
Nun,
da ich noch nicht weiss wie ich die register auslesen kann (hab keine api), ich aber weiss wie ich diese ports an und ausschalten kann ,habe ich versucht es auf diese weise zu Lösen.

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
procedure TForm4.Switch2Switch(Sender: TObject);
begin
    //o_register[1] := 0;
       case o_register[2of

             0Begin
                   if o_register[1] = 0 then
                     begin
                        DomoSend($3c$00$ff$00$00$00$00$00$00$FE);
                        o_register[2] := 1;
                        Memo1.Lines.Add('P2 On');
                     end;
                   if o_register[1] = 1 then
                     begin
                       DomoSend($3c$ff$ff$00$00$00$00$00$00$FE);
                       o_register[2] := 1;
                       Memo1.Lines.Add('P2 On');
                    end;
                 End;

             1begin
                   if o_register[1] = 1 then
                     begin
                        DomoSend($3c$ff$00$00$00$00$00$00$00$FE);
                        o_register[2] := 0;
                       Memo1.Lines.Add('P2 Off');
                     end;
                     if o_register[1] = 0 then
                     begin
                        DomoSend($3c$00$00$00$00$00$00$00$00$FE);
                        o_register[2] := 0;
                       Memo1.Lines.Add('P2 Off');
                     end;
             end;
    end;
end;


Das ist allerdings nicht sehr effectiv und es wird ja enorm an Aufwand für 8 ports...
Ich hoffe dass ich mich jetzt besser erklären konnte.

Moderiert von user profile iconChristian S.: Code- durch Delphi-Tags ersetzt
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10181
Erhaltene Danke: 1254

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: So 28.06.15 12:27 
Moin!

Die Herausforderung bei dir besteht echt darin, deine Postings zu verstehen, nicht Tipps zu geben... :lupe: :gruebel: :les: :nixweiss:

Kann es sein, dass du die Unterschiede vom Ist- zum Soll-Zustand ermitteln möchtest? Und dann nur die notwendigen Änderungen an die Hardware übertragen willst? Ehrlich gesagt bringt mich der Quelltext auch nicht weiter. Außer, dass ich mir sicher bin, dass man das optimieren kann, verstehe ich nicht, was da passiert. :?

Sind denn die Portzustände in einem Byte zusammengefasst, also überträgst du immer alle Relaiszustände auf einmal? Oder kannst/musst du die Relais einzeln ansteuern?

Wie ist das Konzept deiner GUI und der Controls aufgebaut? Im einfachsten Fall stelle ich mir 8 Checkboxen vor und beim Anklicken ändert sich der Relaiszustand.

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
jeng Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 30



BeitragVerfasst: So 28.06.15 12:52 
Hallo Narses,

Du hast sicherlich Recht, dass es mir schwer fällt mich richtig zu erklären, naja ich veruch mein bestes.

Wie du schon beschieben hast, hab ich auf der gui einen connect button, ein memo feld , 2 switches, und ein paar labels.

Ich muss jedesmal die ganze byte folge an das modul senden.

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
procedure TForm4.DomoSend(para1: byte; port1: byte; port2: byte; port3: byte;
  port4: byte; port5: byte; port6: byte; port7: byte; port8: byte);

var
  Buf: TIdBytes;
begin

  SetLength(Buf, 14);
  // Exo1 Port1 OFF Hex: 23 3c 15 0a 01 00 00 00 00 00 00 00 00 fe
  // Exo1 Port1 ON  Hex: 23 3c 15 0a 01 ff 00 00 00 00 00 00 00 fe
  ----------------------------------Port1--2--3--4--5--6--7--8-----
  
  FillBytes(Buf, 140); 
  Buf[0] := $23;
  Buf[1] := para1; // Exo1 modul1 ist $3C, modul2 ist $60, modul 3 ist $61, etc... 
  Buf[2] := $15;
  Buf[3] := $0A;
  Buf[4] := $01;
  Buf[5] := port1;
  Buf[6] := port2;
  Buf[7] := port3;
  Buf[8] := port4;
  Buf[9] := port5;
  Buf[10] := port6;
  Buf[11] := port7;
  Buf[12] := port8;
  Buf[13] := $fe;

  IdUDPClient1.Sendbuffer(IP, strtoint(Edit2.Text), Buf);
        //  ReceivedString := IdUDPClient1.ReceiveString();
  
end;
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10181
Erhaltene Danke: 1254

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: So 28.06.15 13:02 
Moin!

Ich verstehe leider immer noch nicht dein Problem. :? :nixweiss: Was hindert dich daran einfach bei einer Änderung eines Switches immer alle aktuellen Switch-Zustände zu übertragen?

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
jeng Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 30



BeitragVerfasst: So 28.06.15 13:10 
user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
Moin!


Kann es sein, dass du die Unterschiede vom Ist- zum Soll-Zustand ermitteln möchtest? Und dann nur die notwendigen Änderungen an die Hardware übertragen willst?
cu
Narses


Ich weiss ja nicht ob man das Ist / Soll Zustand nennt.

Port 1 Ist an.
23 3c 15 0a 01 ff 00 00 00 00 00 00 00 fe
Port 2 Ist an.
23 3c 15 0a 01 00 ff 00 00 00 00 00 00 fe

wie kann ich nun feststellen ob, wenn ich port 2 ausschalte nich auch port 1 ausgeschaltet wird.

Port 2 Aus.
23 3c 15 0a 01 00 00 00 00 00 00 00 00 fe
Da di 8 bytes nun auf null sind wird das ganze modul ausgeschaltet
weil ich ja den status der anderen ports nicht habe.
Also ich muss irgendwie die zustände der anderen ports speichern und abfragen!
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10181
Erhaltene Danke: 1254

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: So 28.06.15 13:17 
Moin!

Wenn du den aktuellen Zustand nicht von der Hardware abfragen kannst, dann hast du ja nur deine GUI-Controls (bzw. allgemein: die im Programm gespeicherten Zustände). :nixweiss: Also überträgst du diese bei einem Klick einfach (es kann sich ja pro Ereignis nur ein Wert ändern). :idea:

cu
Narses

//Edit: oder soll der Zustand nicht nach jeder Änderung übertragen werden, so dass du Probleme hast, die Änderungen zu verfolgen?
Hm... Oder siehst du das Problem bei einem Neustart der Anwendung, da du dann den aktuellen Zustand der Hardware nicht (mehr) hast?

//Edit2: hättest du gerne mal ein Beispiel, wie ich das machen würde? Vielleicht kommen wir so weiter... :gruebel:

_________________
There are 10 types of people - those who understand binary and those who don´t.
jeng Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 30



BeitragVerfasst: So 28.06.15 13:53 
user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
Moin!

//Edit: oder soll der Zustand nicht nach jeder Änderung übertragen werden, so dass du Probleme hast, die Änderungen zu verfolgen?
Hm... Oder siehst du das Problem bei einem Neustart der Anwendung, da du dann den aktuellen Zustand der Hardware nicht (mehr) hast?

//Edit2: hättest du gerne mal ein Beispiel, wie ich das machen würde? Vielleicht kommen wir so weiter... :gruebel:


Zu verfolgen, ich glaube das ist genau die richtige Wort wahl.

wenn ich also port 1 auf 0n stelle sieht das ja so aus.

Port 1 on 23 3c 15 0a 01 ff 00 00 00 00 00 00 00 fe
nun stelle ich Port 2 zusäzlich auf on ohne port 1 auszuschalten!

Port 2 on 23 3c 15 0a 01 ff ff 00 00 00 00 00 00 fe

nun möchte ich Port2 ausschalten aber Port 1 soll an bleiben.

Port2 aus mit Port1 an: 23 3c 15 0a 01 ff 00 00 00 00 00 00 00 fe

Und da ist mein problem, wie schon erwähnt kann ich ja den status nicht abfragen, was noch auf an geschaltet ist.
Deshalb muss ich irgendwie in dem programm den zustand der anderen ports speichern.


Legende:
Nur Port 1 on 23 3c 15 0a 01 ff 00 00 00 00 00 00 00 fe
Nur Port 2 on 23 3c 15 0a 01 00 ff 00 00 00 00 00 00 fe
Nur Port 3 on 23 3c 15 0a 01 00 00 ff 00 00 00 00 00 fe
Nur Port 4 on 23 3c 15 0a 01 00 00 00 ff 00 00 00 00 fe
Nur Port 5 on 23 3c 15 0a 01 00 00 00 00 ff 00 00 00 fe
Nur Port 6 on 23 3c 15 0a 01 00 00 00 00 00 ff 00 00 fe
Nur Port 7 on 23 3c 15 0a 01 00 00 00 00 00 00 ff 00 fe
Nur Port 8 on 23 3c 15 0a 01 00 00 00 00 00 00 00 ff fe

Alles an: 23 3c 15 0a 01 ff ff ff ff ff ff ff ff fe
Alles aus: 23 3c 15 0a 01 00 00 00 00 00 00 00 00 fe

Und der zustand "muss" nach jeder änderung übertragen werden, weil ja sonst nichts geschaltet wird.
Ich glaube dass ein kleines beispiel vieleicht helfen könnte.

Ich bin dir auf jeden fall schon mal sehr dankbar für deine geduld und hilfe!!
Perlsau
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: So 28.06.15 15:04 
Natürlich mußt du den Zustand speichern, was sonst?

Du hast also die ersten fünf Bytes, die immer gleich bleiben, und das letzte Byte, das auch immer auf fe bleibt. Die dazwischenliegenden Bytes stellen deine Ports dar, von 1 bis 8. Soweit okay.

Jetzt schickst du beim Programmstart eine Bytefolge, die den Port 1 einschaltet. Diese Bytefolge speicherst du. Und an dieser Bytefolge siehst du auch jederzeit, welche Ports ein- und welche ausgeschaltet sind. Willst du den Zustand eines Ports ändern, änderst du die Bytefolge entsprechend und speicherst diese wieder. So stellt diese Bytefolge immer den aktuellen Zustand dar. Wo ist da das Problem?
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10181
Erhaltene Danke: 1254

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: So 28.06.15 16:20 
Moin!

OK, hier ein Beispiel:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
type
  TForm1 = class(TForm)
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
    procedure ckPortClick(Sender: TObject);
    procedure SendStateToHW;
  private
    { Private-Deklarationen }
  public
    PortState: array[0..7of Boolean;
  end;

implementation

procedure TForm1.FormCreate(Sender: TObject);
  var
    i: Integer;
    CheckBox: TCheckBox;
begin
  for i := 0 to 7 do begin
    CheckBox := TCheckBox.Create(Self);
    CheckBox.Parent := Self;
    CheckBox.Left := 16;
    CheckBox.Top := 16 +24*i;
    CheckBox.Width := 97;
    CheckBox.Height := 17;
    CheckBox.Caption := 'Port' +IntToStr(i +1);
    CheckBox.Tag := i;
    CheckBox.OnClick := ckPortClick;
    PortState[i] := FALSE;
  end;
end;

procedure TForm1.ckPortClick(Sender: TObject);
  var
    ThisCheckBox: TCheckBox;
begin
  ThisCheckBox := Sender as TCheckBox;
  PortState[ThisCheckBox.Tag] := ThisCheckBox.Checked;
  SendStateToHW;
end;

procedure TForm1.SendStateToHW;
  var
    i: Integer;
    Line: String;
begin
  Line := 'NewState=';
  for i := 0 to 7 do
    if PortState[i] then
      Line := Line +'FF,'
    else
      Line := Line +'00,';
  Memo1.Lines.Add(Line);
end;

GUI:
Screen

Bei Fragen: fragen. ;)

cu
Narses

//EDIT: Hab den Code nochmal auf dynamische Checkboxen umgestellt, damit wird es einfacher die Demo nur aus dem Code zu verstehen, ohne das Projekt öffnen zu müssen. :idea:
Einloggen, um Attachments anzusehen!
_________________
There are 10 types of people - those who understand binary and those who don´t.
jeng Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 30



BeitragVerfasst: So 28.06.15 20:07 
Wow, also das klappt ja wunderbar!!
Ich hab den code ein bischen umgebaut, aber wie gesagt genial.

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
procedure TForm4.SendStateToHW;
  var
    i: Integer;
    Line: String;
    Port: array [0..7of Byte;

begin
   if not IdUDPClient1.Connected then
      Begin
         ShowMessage('Please connect.');
         Exit;
      End
   else

  //Line := 'NewState=';
  for i := 0 to 7 do
    if PortState[i] then
        // Line := Line +'FF,';
         Port[i] := $FF
      else
        //Line := Line +'00,';
        Port[i] :=  $00;
        DomoSend($3C, Port[0], Port[1], Port[2], Port[3], Port[4], Port[5], Port[6], Port[7], $FE);
        //Memo1.Lines.Add(line);
       end;

procedure TForm4.PortSwitch(Sender: TObject);
  var
    ThisSwitch: TSwitch;
 begin
  ThisSwitch := Sender as TSwitch;

  PortState[ThisSwitch.Tag] := ThisSwitch.IsChecked;
  //Memo1.Lines.Add(IntToStr(ThisSwitch.Tag));
  SendStateToHW;
end;


Ich werde noch ein bischen mit dem Democode herumspielen.
Ich Danke dir vielmals für deine Mühe.
Das hat mir jetzt sehr weiter geholfen.
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: So 28.06.15 22:53 
jeng Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 30



BeitragVerfasst: Do 27.08.15 12:29 
Hallo,

Ich hab da eine kleine Frage ;-)

user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
Moin!
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
procedure TForm1.SendStateToHW;
  var
    i: Integer;
    Line: String;
begin
  Line := 'NewState=';
  for i := 0 to 7 do
    if PortState[i] then
      Line := Line +'FF,'
    else
      Line := Line +'00,';
  Memo1.Lines.Add(Line);
end;

GUI:
[Bild: Screen]

Bei Fragen: fragen. ;)


Ich versuche gerade diese Procedure umzubauen. Nur komme ich nicht so richtig weiter.
Wie kann Ich mit PortState[i] meine Switches auf IsChecked setzen ohne den onclick auszuführen?
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
procedure TfrmMain.SetPortOn;
Var i: integer;
    ThisSwitch: TSwitch;
Begin
   for i := 0 to 7 do
      if PortState[i] then
      ThisSwitch.IsChecked := PortState[i];  
End;


Also so funktionniert das nicht.
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 27.08.15 20:12 
- Nachträglich durch die Entwickler-Ecke gelöscht -

Für diesen Beitrag haben gedankt: jeng
jeng Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 30



BeitragVerfasst: Di 15.09.15 21:23 
Hallo,

Ich kriegs einfach nicht gebacken...

Ich habe Narses beispiel ein "bischen" ausgebaut. ;-)

Aus dem PortState array habe ich ein 2d array gebaut weil ich 16 Exo´s (aparate) mit jeweils 8 ports haben kann.

Jetzt scanne ich erst einmal den bus ab um zu schauen wievile Exos da sind, und was auch schon von ports auf dem jeweiligen Exo auf on also "FF" geschaltet ist und setze diese ports dann schon mal auf on.

Nun habe ich das problem wenn ich mich auf Exo 0 verbinde dann klappt das auch ohne probleme.
Wenn ich aber auf Exo 1 wechsele dann schaltet er mir die ports sporadisch auf on.
zb. ich klicke auf switch 1, dann geht auch port 1 an, und auf einmal dann auch port 4 oder 7...

Ich kann es leider im moment nur mit 2 exos testen da ich nur zwei hab. (weitere sind aber schon geordert).

Ich währe sehr froh für hilfe oder an verbesserungen von meinem bestimmt "grausigen code".

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291:
292:
293:
294:
295:
296:
297:
298:
299:
300:
301:
302:
303:
304:
305:
306:
307:
308:
309:
310:
311:
312:
313:
314:
315:
316:
317:
318:
319:
320:
321:
322:
323:
324:
325:
326:
327:
328:
329:
330:
331:
332:
333:
334:
335:
336:
337:
338:
339:
340:
341:
342:
343:
344:
345:
346:
347:
348:
349:
350:
351:
352:
353:
354:
355:
356:
357:
358:
359:
360:
361:
362:
363:
364:
Function ExoScan(exoport: Integer): Integer; //über button click (For c := 60 to 75  do  begin  ExoScan(c);  end;)
var
  ExoSBuf: AnsiString;
  Data, X, Y, ExoAnswer: String;
  n,i,v: Integer;

Begin
  frmMain.ClearStatus;
  frmMain.ClearExo;

  frmMain.Timer1.Enabled := False;
  Data := '';
  n := 0;
  i := 0;
  v := 0;
  X := HexToString(IntToHex(exoport, 1)); // '$'+IntToHex(i, 1);
  ExoSBuf := #$04#$01#$02#$23 + X + #$00#$02#$49#$49;
  ExoAnswer := #$04#$01#$23#$00 + X + #$07// #$3b;
  sock.SendString(ExoSBuf);
  sleep(99);
  Data := sock.RecvPacket(500);
  X := Copy(Data, 36);

  if ExoAnswer = X then
     Begin
      Y := Copy(X, 51);
    //  frmMain.Memo1.Lines.Add('Exo:' + IntToStr(exoport mod 6 +1) + ' ' +
    //  StringToHex(Y)); // +' ' +Buf);
      i := exoport mod 6 +1;
      TRadioButton(frmMain.GroupBox2.Controls[i]).Enabled := True;
      TRadioButton(frmMain.GroupBox2.Controls[i]).Visible := True;
      frmMain.RadioButton1.IsChecked := True;  //immer Exo1 Auswählen nach bus scan
      for n := 60 to exoport mod 6 do
          frmMain.ExoTrue[n] := True;
        // frmMain.PortState[n,Nil] := True;
        //  frmMain.PortState1[n] := True;
      End;
      frmMain.Timer1.Enabled := True;
  //   Result :=n;
end;


Procedure TfrmMain.ScanStatus; //Hier wird gescannt im timer1 alle 1 sekunden. Soll Portstate[x,i] überschreiben! 
Const
  scan = #$05#$01;

Var
  S, X: String;
  I,Y,Exo,PortOn,n,m: Integer;
  Buf: String;
  source1: String;
begin
   {$ZEROBASEDSTRINGS OFF}
   Exo := 0;
   PortOn := 0;

  sock.SendString(scan);
  Buf := sock.RecvPacket(500);
  S := Buf.Substring(2,High(Buf));
  // Source1 := #$FF;
  source1 := #$01;

  for I := 0 to high(S) -1 do // so sind es immer 128 bytes, also maximal 16 exos a 8 ports.
     //if (I = 128) And (S[I] > source1) then 

         if S[i] > source1 then

            begin

            Exo := (I) div 8;
              if Exo = 0 then
                 PortOn := (I) mod 8 -1
              else
                 PortOn := (I) mod 8;

             //  if ExoTrue[Exo] then
                 PortState[Exo,PortOn] := True
               //  else
               //  PortState[Exo,PortOn] := False;
                //PortState1[PortOn] := True
             end;
            // Memo1.Lines.Add(Format('ScanStatus-Exo%d: %d',[Exo, PortOn])); //[(i) div 8, (i) mod 8]));
             Label13.Text := IntToStr(length(S));

End;

procedure TfrmMain.swPortClick(Sender: TObject);
var
  ThisSwitch: TSwitch;
begin

  ThisSwitch := Sender as TSwitch;
  ThisSwitch.OnClick := Nil;

  Exo := Exodet[SelectedExo];
  ExoTrue[SelectedExo] := True;
  PortState[SelectedExo,ThisSwitch.Tag] := ThisSwitch.IsChecked;
  //PortState1[ThisSwitch.Tag] := ThisSwitch.IsChecked;
  LastExoPort := ThisSwitch.Tag;

  Memo1.Lines.Add('Send to Exo:' + IntToStr(SelectedExo) + ' : ' + IntToStr(ThisSwitch.Tag));
  SendStateToHW;
  //sleep(99);
end;

procedure TfrmMain.SendStateToHW;
var
  I,N: Integer;
  Dim,IsDim: ansichar;
  Temp,Line: String;

  begin

  if IsSocketAlive(sock) = True then
  Begin
    ShowMessage('Please connect.');
    exit;
  End;
  if IsSocketAlive(sock) = False then

  Begin
    Line := 'Exo:'+IntToStr(SelectedExo)+'NewState=';
    if ExoTrue[selectedExo] then
       for i  := 0 to 7 do
        if PortState[selectedExo,i] then
        //if PortState1[i] then
           begin
      //     Line := Line +'FF,';
           Port[i] := #$FF;
           Dim := #$FE;
           end
          else
           Begin
       //    Line := Line +'00,';
           Port[i] := #$00;
           Dim := #$01;
              End;
        Memo1.Lines.Add(Line);
        DomoSend(Port[0], Port[1], Port[2], Port[3], Port[4], Port[5], Port[6], Port[7], Dim);

  End;



Procedure TfrmMain.DomoSend(port1: ansichar; port2: ansichar; port3: ansichar;
  port4: ansichar; port5: ansichar; port6: ansichar; port7: ansichar;
  port8: ansichar; para3: ansichar);
var
  Buf,Buf1: AnsiString;
  Data: String;
  I: Integer;

begin

  Data := #$04#$01#$02#$23 + Exo + #$00#$0a#$01 + port1 + port2 + port3 + port4
    + port5 + port6 + port7 + port8 + para3;

  sock.SendString(Data);// + CRLF);

  for I := 1 to High(Data) do
  begin
    Buf := Data.Substring(4,High(Data));
    Buf1 := Buf1 + StringToHex(Buf[I]);
  end;
  Memo1.Lines.Add(Buf1);
end;

Procedure SetPortOn; //hier werden die gescannten ports auf on geswitchd.

Var
  X: Integer;
  OldState: TNotifyEvent;

begin

for X := 0 to 7 do
   if frmMain.PortState[frmMain.SelectedExo,X] then
  // if frmMain.PortState1[X] then
    begin
       OldState := frmMain.u[X].OnSwitch;
       frmMain.u[X].OnSwitch := nil;
       frmMain.u[X].IsChecked := True;
       frmMain.u[X].OnSwitch := OldState;
    End
    else if frmMain.PortState[frmMain.SelectedExo,X] = False then
    //if frmMain.PortState1[X] = False then
    begin
        OldState := frmMain.u[X].OnSwitch;
        frmMain.u[X].OnSwitch := nil;
        frmMain.u[X].IsChecked := False;
        frmMain.u[X].OnSwitch := OldState;
    End;

end;

procedure TfrmMain.ClearStatus;

var n,m: integer;
Begin
  for n  := 0 to 15 do
      Begin
        for m := 0 to 7 do
           PortState[n,m] := False;
    //  PortState1[m] := False;
     // sleep(99);
      End;
End;

procedure TfrmMain.ClearExo;
Var m: integer;
begin
    for m := 0 to 15 do
     // PortState[n,m] := False;
      ExoTrue[m] := False;
     // sleep(99);
end;

procedure TfrmMain.RadioButtonClick(Sender: TObject); //Hier werden die Exos gewechselt.
Var
  I, X, Y: Integer;

Begin
   SelectedExo := 0;
{
   case (Sender as TRadioButton).Tag of
     0: Begin
        //ClearExo;
        ClearStatus;
        Memo1.lines.add('Cleared 1 ');
        End;
     1: Begin
        //ClearExo;
        ClearStatus;
        Memo1.lines.add('Cleared 2 ');
        End;
   end;
  }

  I := TRadioButton(Sender).Tag;
  Exo := Exodet[I];
  ExoTrue[I] := True;
  SelectedExo := I;
  Memo1.lines.add('Radio Change '+StringToHex(Exo)+'  ' +Exodet[I]);

End;

procedure TfrmMain.Timer1Timer(Sender: TObject); //hier wird alle 1 sec neu eingelesen und portstate neu gesetzt.
begin
   ScanStatus;
     SetPortOn;
end;

procedure TfrmMain.Timer2Timer(Sender: TObject);
begin
  Label4.Text := TimeToStr(Time - StartTime);

end;

procedure TfrmMain.FormCreate(Sender: TObject); //hier noch formcreate.
Var
  I,X: Integer;
  R: TBinaryReader;

begin
  //Memo1.VScrollBar.Value := Memo1.VScrollBar.Max;
  Label1.StyledSettings := Label1.StyledSettings - [TStyledSetting.FontColor];
  Label3.StyledSettings := Label3.StyledSettings - [TStyledSetting.FontColor];
  Label1.Text := ('Disconnected');
  Label1.FontColor := TAlphaColors.Red;
  Button1.Enabled := False;
  SelectedExo := 0;

  // RadioButton1.IsChecked := True;
  // RadioButtonTag := 1; //IsChecked := True;
  GroupBox1.Opacity :=0;
  GroupBox2.Opacity :=0;
  Memo1.Opacity :=0.5;
  Panel1.Opacity :=0;

  GroupBox1.Controls.Add(Switch1);
  GroupBox1.Controls.Add(Switch2);
  GroupBox1.Controls.Add(Switch3);
  GroupBox1.Controls.Add(Switch4);
  GroupBox1.Controls.Add(Switch5);
  GroupBox1.Controls.Add(Switch6);
  GroupBox1.Controls.Add(Switch7);
  GroupBox1.Controls.Add(Switch8);



  u[0] := Switch1;
  u[1] := Switch2;
  u[2] := Switch3;
  u[3] := Switch4;
  u[4] := Switch5;
  u[5] := Switch6;
  u[6] := Switch7;
  u[7] := Switch8;

  GroupBox2.Controls.Add(RadioButton1);
  GroupBox2.Controls.Add(RadioButton2);
  GroupBox2.Controls.Add(RadioButton3);
  GroupBox2.Controls.Add(RadioButton4);
  GroupBox2.Controls.Add(RadioButton5);
  GroupBox2.Controls.Add(RadioButton6);
  GroupBox2.Controls.Add(RadioButton7);
  GroupBox2.Controls.Add(RadioButton8);

 RadioButton1.Tag :=0;
  RadioButton2.Tag :=1;
   RadioButton3.Tag :=2;
    RadioButton4.Tag :=3;
     RadioButton5.Tag :=4;
      RadioButton6.Tag :=5;
       RadioButton7.Tag :=6;
        RadioButton8.Tag :=7;

 Switch1.Tag := 0;
  Switch2.Tag := 1;
   Switch3.Tag := 2;
    Switch4.Tag := 3;
     Switch5.Tag := 4;
      Switch6.Tag := 5;
       Switch7.Tag := 6;
        Switch8.Tag := 7;

  Exodet[0] := #$3c;
  Exodet[1] := #$3d;
  Exodet[2] := #$3e;
  Exodet[3] := #$3f;
  Exodet[4] := #$40;
  Exodet[5] := #$41;
  Exodet[6] := #$42;
  Exodet[7] := #$43;
  Exodet[8] := #$44;
  Exodet[9] := #$45;
  Exodet[10] := #$46;
  Exodet[11] := #$47;
  Exodet[12] := #$48;
  Exodet[13] := #$49;
  Exodet[14] := #$4a;
  Exodet[15] := #$4b;

  Exo := Exodet[0];
  FillChar(Port, 8#$00);     //set domoports to zero.

 
  if SaveState.Stream.Size > 0 then
  begin
    // Recover previously typed text in Edit1 control.
    R := TBinaryReader.Create(SaveState.Stream);
    try
      Edit1.Text := R.ReadString;
      Edit2.Text := R.ReadString;
      Edit3.Text := R.ReadString;
      Edit4.Text := R.ReadString;
    finally
      R.Free;
    end;

  end;

  sock := TTCPBlockSocket.Create;

end;