Пример #1
0
uint8_t get_heiz_details(uint8_t heiz_id, 
		uint8_t *mode,
		uint8_t *rate,
		int16_t *Tsoll,
		uint16_t *dauer,
		uint16_t *Tist)
{
	canix_frame message;

	heiz_details_heiz_id = heiz_id;
	heiz_details_Tsoll = 0;

	message.src = canix_selfaddr();
	message.dst = HCAN_MULTICAST_CONTROL;
	message.proto = HCAN_PROTO_SFP;
	message.data[0] = HCAN_SRV_HES;
	message.data[1] = HCAN_HES_HEIZUNG_DETAILS_REQUEST;
	message.data[2] = heiz_id;
	message.size = 3;
	canix_frame_send_with_prio(&message, HCAN_PRIO_HI);
	heiz_details_expected = 1; // Bit 0 = HCAN_HES_HEIZUNG_DETAILS_REQUEST

	// Auf die Anwort warten
	canix_sleep_100th(5);

	// ... und noch nach T(ist) fragen...
	message.data[1] = HCAN_HES_HEIZUNG_TIST_REQUEST;
	message.data[2] = heiz_id;
	message.size = 3;
	canix_frame_send_with_prio(&message, HCAN_PRIO_HI);
	heiz_details_expected = 2; // Bit 1 = HCAN_HES_HEIZUNG_TIST_REQUEST

	// Auf die Anwort warten
	canix_sleep_100th(5);

	if (heiz_details_expected == 0)
	{
		// aha, es ist eine Antwort eingetroffen...

		*mode = heiz_details_mode;
		*rate = heiz_details_rate;
		*Tsoll = heiz_details_Tsoll;
		*Tist = heiz_details_Tist;
		*dauer = heiz_details_dauer;
		heiz_details_heiz_id = 0;

		return 0;
	}

	// Timeout... keine Antwort erhalten :-(
	return 1;
}
Пример #2
0
void powerport_page_print_page(eds_powerport_page_block_t *p)
{
	char s[40];
	canix_frame message;

	// LCD Bildschirm loeschen
	lcd_clrscr();

	// 1. Zeile
	snprintf_P(s,sizeof(s), PSTR("%s"), p->line0); 
	lcd_gotoxy(0,0);
	lcd_puts(s);

	snprintf_P(s,sizeof(s), PSTR("%s"), p->line1); 
	lcd_gotoxy(0,1);
	lcd_puts(s);

	// In powerport_page_state wird spaeter der State gespeichert; sollte
	// keine Meldung eintreffen, so nuetzt es nichts, wenn der User OK
	// drueckt - man weiss ja den State nicht und kann ihn nicht aendern!
	// Das erkennt man am Wert -1
	powerport_page_state = -1;
	powerport_page_timer = -1;

	// nun den Status des Powerports erfragen und (asynchron)
	// in powerport_page_can_callback weitermachen

	message.src = canix_selfaddr();
	message.dst = HCAN_MULTICAST_CONTROL;
	message.proto = HCAN_PROTO_SFP;
	message.data[0] = HCAN_SRV_HES;
	message.data[1] = HCAN_HES_POWER_GROUP_STATE_QUERY;
	message.data[2] = p->gruppe;
	message.size = 3;
	canix_frame_send_with_prio(&message, HCAN_PRIO_HI);

	canix_sleep_100th(1);

	message.src = canix_selfaddr();
	message.dst = HCAN_MULTICAST_CONTROL;
	message.proto = HCAN_PROTO_SFP;
	message.data[0] = HCAN_SRV_HES;
	message.data[1] = HCAN_HES_POWER_GROUP_TIMER_QUERY;
	message.data[2] = p->gruppe;
	message.size = 3;
	canix_frame_send_with_prio(&message, HCAN_PRIO_HI);

}
Пример #3
0
void rolladen_page_handle_key_down_event(eds_rolladen_page_block_t *p, 
		uint8_t key)
{
	if (key == KEY_OK)
	{
		canix_frame message;

		message.src = canix_selfaddr();
		message.dst = HCAN_MULTICAST_CONTROL;
		message.proto = HCAN_PROTO_SFP;
		message.data[0] = HCAN_SRV_HES;
		message.data[1] = HCAN_HES_ROLLADEN_POSITION_SET;
		message.data[2] = p->gruppe;
		message.data[3] = p->pos;
		message.size = 4;
		canix_frame_send_with_prio(&message, HCAN_PRIO_HI);

		lcdctrl_blink();

		return;
	}

	if (key == KEY_ESC)
	{
		goto_page_up();
		return;
	}

	if (key == KEY_UP)
		goto_prev_page();

	if (key == KEY_DOWN)
		goto_next_page();
}
Пример #4
0
static inline void sendMessage(device_data_schalter *p, uint8_t active)
{
	canix_frame message;

	if(active)
		p->lastEdge = RISING;
	else
		p->lastEdge = FALLING;


	if(p->config.feature & (1<<FEATURE_SCHALTER_INVERTIEREN))
		active = !active; // invertieren

	message.src = canix_selfaddr();
	message.dst = HCAN_MULTICAST_CONTROL;
	message.proto = HCAN_PROTO_SFP;
	message.data[0] = HCAN_SRV_HES;
	if(active)
	{
		if(p->config.feature & (1<<FEATURE_SCHALTER_MUTE))
			message.data[1] = HCAN_HES_MUTE_ON;
		else message.data[1] = HCAN_HES_SCHALTER_ON;
	}
	else
	{
		if(p->config.feature & (1<<FEATURE_SCHALTER_MUTE))
			message.data[1] = HCAN_HES_MUTE_OFF;
		else message.data[1] = HCAN_HES_SCHALTER_OFF;
	}
	message.data[2] = p->config.gruppe;
	message.size = 3;
	canix_frame_send_with_prio(&message, HCAN_PRIO_HI);
}
Пример #5
0
uint8_t get_weck_details(uint8_t weck_id, uint16_t *dauer)
{
	canix_frame message;

	weck_details_weck_id = weck_id;

	message.src = canix_selfaddr();
	message.dst = HCAN_MULTICAST_CONTROL;
	message.proto = HCAN_PROTO_SFP;
	message.data[0] = HCAN_SRV_HES;
	message.data[1] = HCAN_HES_WECKER_DETAILS_REQUEST;
	message.data[2] = weck_id;
	message.size = 3;
	canix_frame_send_with_prio(&message, HCAN_PRIO_HI);
	weck_details_expected = 1; // Bit 0 = HCAN_HES_WECKER_DETAILS_REQUEST

	// Auf die Anwort warten
	canix_sleep_100th(5);

	if (weck_details_expected == 0)
	{
		// aha, es ist eine Antwort eingetroffen... (und zwar HCAN_HES_WECKER_DETAILS)

		*dauer = weck_details_dauer;
		weck_details_weck_id = 0;

		return 0;
	}

	// Timeout... keine Antwort erhalten :-(
	return 1;
}
Пример #6
0
void set_weck_edited_details(eds_weck_page_block_t *p)
{
	canix_frame message;

	// 1. herausfinden, welcher Parameter geaendert wurde
	message.src = canix_selfaddr();
	message.dst = HCAN_MULTICAST_CONTROL;
	message.proto = HCAN_PROTO_SFP;
	message.data[0] = HCAN_SRV_HES;
	message.data[1] = HCAN_HES_WECKER_SET;
	message.data[2] = p->weck_id; //=Powerport-Gruppe

	message.data[3] = POWERPORT_FEATURE_WECK_VERZOEGERT_EIN; //Vorbelegung
	if ( p->feature & (1<<POWERPORT_FEATURE_WECK_VERZOEGERT_EIN) )
	{
		message.data[3] = POWERPORT_FEATURE_WECK_VERZOEGERT_EIN;
	}
	else if ( p->feature & (1<<POWERPORT_FEATURE_WECK_AUTO_AUS) )
	{
		message.data[3] = POWERPORT_FEATURE_WECK_AUTO_AUS;
	}

	message.data[4] = weck_details_dauer_edit >> 8; //Dauer bis Wecker einschaltet
	message.data[5] = weck_details_dauer_edit; //LSB
	message.size = 6;

	canix_frame_send_with_prio(&message, HCAN_PRIO_HI);

}
Пример #7
0
inline void rolladenSchlitzpos_timer_handler(device_data_rolladenSchlitzpos *p, uint8_t zyklus)
{
	if (zyklus != 10) return; // 10tel-Sekunden-Zyklus verwendet

	canix_frame message;

	if(p->rolladenSchlitzJob < SCHLITZ_JOB_ABGEMELDET) //ist der Job angemeldet
	{
		p->rolladenSchlitzJob--; //es sind wieder 100 ms vergangen
		//canix_syslog_P(SYSLOG_PRIO_DEBUG, PSTR("p->rolladenSchlitzJob=%d"), p->rolladenSchlitzJob);
		if(p->rolladenSchlitzJob == 0)
		{
			p->rolladenSchlitzJob = SCHLITZ_JOB_ABGEMELDET;

			/* Warte zwei Sekunden. Falls das Fenster wieder geoeffnet wird,
			 * wird der rolladenSchlitzJob wieder abgemeldet,
			 * die HCAN_HES_REEDKONTAKT_STATE_QUERY nicht gesendet
			 * und somit der Rollladen nicht geschlossen.
			 * ...und dann in HCAN_HES_REEDKONTAKT_STATE_REPLAY die Abfrage,
			 * ob der Reedkontakt immer noch zu ist: */
			message.src = canix_selfaddr();
			message.dst = HCAN_MULTICAST_CONTROL;
			message.proto = HCAN_PROTO_SFP;
			message.data[0] = HCAN_SRV_HES;

			message.data[1] = HCAN_HES_ROLLADEN_POSITION_REQUEST;
			message.data[2] = p->config.rolladen;
			message.size = 3;
			canix_frame_send_with_prio(&message, HCAN_PRIO_HI); //rolladenIstposition-Abfrage

			//und Reedkontakt(e) abfragen:
			message.data[1] = HCAN_HES_REEDKONTAKT_STATE_QUERY;
			message.data[2] = p->config.reed0;
			message.size = 3;
			canix_frame_send_with_prio(&message, HCAN_PRIO_LOW);

			if(p->config.reed1 != 255) //zweiter Reedkontakt vorhanden?
			{
				message.data[2] = p->config.reed1;
				canix_frame_send_with_prio(&message, HCAN_PRIO_LOW);
			}
		}
	}
}
Пример #8
0
void taster_page_handle_key_down_event(eds_taster_page_block_t *p, 
		uint8_t key)
{
	if (key == KEY_OK)
	{
		canix_frame message;

		message.src = canix_selfaddr();
		message.dst = HCAN_MULTICAST_CONTROL;
		message.proto = HCAN_PROTO_SFP;
		message.data[0] = HCAN_SRV_HES;
		message.data[1] = HCAN_HES_TASTER_DOWN;
		message.data[2] = p->gruppe;
		message.size = 3;
		canix_frame_send_with_prio(&message, HCAN_PRIO_HI);

		canix_sleep_100th(1);
		
		message.data[1] = HCAN_HES_TASTER_UP;
		message.size = 3;
		canix_frame_send_with_prio(&message, HCAN_PRIO_HI);

		lcdctrl_blink();

		return;
	}

	if (key == KEY_ESC)
	{
		goto_page_up();
		return;
	}

	if (key == KEY_UP)
		goto_prev_page();

	if (key == KEY_DOWN)
		goto_next_page();
}
Пример #9
0
static inline void sendMessage(device_data_zentralheizungspumpe *p, uint8_t zustandToSend)
{
	canix_frame message;

	message.src = canix_selfaddr();
	message.dst = HCAN_MULTICAST_CONTROL;
	message.proto = HCAN_PROTO_SFP;
	message.data[0] = HCAN_SRV_HES;
	message.data[1] = zustandToSend; // Zentralheizungspumpe schalten
	message.data[2] = p->config.gruppe;
	message.size = 3;
	canix_frame_send_with_prio(&message, HCAN_PRIO_HI);
}
Пример #10
0
void send_rolladen_position_set(device_data_rolladenSchlitzpos *p, uint8_t soll_position)
{
	canix_frame message;

	message.src = canix_selfaddr();
	message.dst = HCAN_MULTICAST_CONTROL;
	message.proto = HCAN_PROTO_SFP;
	message.data[0] = HCAN_SRV_HES;
	message.data[1] = HCAN_HES_ROLLADEN_POSITION_SET;
	message.data[2] = p->config.rolladen;
	message.data[3] = soll_position; //gewuenschte Rollladenposition: z.B. Pos: 0=zu, SCHLITZ_POS
	message.size = 4;

	canix_frame_send_with_prio(&message, HCAN_PRIO_LOW);
}
Пример #11
0
/** Der poti_timer_handler liest den ADC-Wert des
 *  konfigurierten Potis und sendet diesen auf den CAN-Bus. */
inline void poti_timer_handler(device_data_poti *p, uint8_t zyklus)
{		
	if (zyklus != 10) return; // 10tel-Sekunden-Zyklus verwendet

	int16_t currentADCvalue;
	
	setADMUX(p->config.port);
	currentADCvalue = getADCvalue();	
		
	if (p->potiTelegramCountdown)
	{
		/* Abfrage, ob sich der ADC-Wert signifikant aenderte,
		 * gegenueber dem Wert im letzten Potitelegramm (Filterung): */
		if ( ( currentADCvalue > (p->lastPotiValue + POTI_VALUE_TOLERANCE) ) ||
			 ( currentADCvalue < (p->lastPotiValue - POTI_VALUE_TOLERANCE) ) )
		{
			//sign. Potiwertaenderung gegenueber dem currentADCvalue
			p->potiTelegramCountdown--;
		}
		else
		{
			//Potiwert wieder der gleiche Wert (oder zumindest in etwa)
			p->potiTelegramCountdown = POTI_TELEGRAM_COUNTDOWN_INIT;
		}
	}
	else //p->potiTelegramCountdown == 0
	{
		//Das Potitelegramm senden:
		p->lastPotiValue = currentADCvalue; //Angleich
		p->potiTelegramCountdown = POTI_TELEGRAM_COUNTDOWN_INIT;
		
		//sende das Potitelegramm: 
		canix_frame message;
	
		message.src = canix_selfaddr();
		message.dst = HCAN_MULTICAST_CONTROL;
		message.proto = HCAN_PROTO_SFP;
		message.data[0] = HCAN_SRV_HES;
		
		message.data[1] = HCAN_HES_POTI_POS_CHANGED;
		message.data[2] = p->config.gruppe;
		message.data[3] = (uint8_t)((currentADCvalue & 0xFF00) >> 8); //high value
		message.data[4] = (uint8_t)currentADCvalue; //low value
		message.size = 5;
		canix_frame_send_with_prio(&message, HCAN_PRIO_LOW);
	}
}
Пример #12
0
static void rolladen_send_changed_info(device_data_rolladen *p, uint8_t pos)
{
	canix_frame message;

	message.src = canix_selfaddr();
	message.dst = HCAN_MULTICAST_INFO;
	message.proto = HCAN_PROTO_SFP;
	message.data[0] = HCAN_SRV_HES;
	message.data[1] = HCAN_HES_ROLLADEN_POSITION_CHANGED_INFO;
	message.data[2] = p->config.taster;
	message.data[3] = pos; // aktuelle Position in %
	message.data[4] = 0; // Quelle des cmd: nicht verwendet
	message.data[5] = 0; // Quelle des cmd: nicht verwendet
	message.size = 6;

	canix_frame_send_with_prio(&message, HCAN_PRIO_HI);
}
Пример #13
0
/**
 * Fragt alle konfigurierten Reedkontakte nach ihrem Status und sammelt
 * die Ergebnisse in fenster_monitor_reed_state; liefert die Anzahl der
 * offenen Reedkontakte zurueck
 */
uint8_t fenster_monitor_collect_reed_states(eds_fenster_monitor_page_block_t 
		*p)
{
	uint8_t i,n_reed_open;
	uint8_t *reeds = (uint8_t *)(&p->reed0);

	// Ergebnis-Array initialisieren:
	for (i = 0; i < 24; i++)
		fenster_monitor_reed_state[i] = 255;

	// ueber alle Reedkontakte iterieren:
	for (i = 0; i < 24; i++)
	{
		if (reeds[i] != 255) // ist es ein konfigurierter Reedkontakt?
		{
			// Nach Kontakt-Status fragen; die Ergebnisse kommen asynchron
			// ueber den CAN Handler rein
			canix_frame message;
			message.src = canix_selfaddr();
			message.dst = HCAN_MULTICAST_CONTROL;
			message.proto = HCAN_PROTO_SFP;
			message.data[0] = HCAN_SRV_HES;
			message.data[1] = HCAN_HES_REEDKONTAKT_STATE_QUERY;
			message.data[2] = reeds[i]; // die Reedkontakt-Gruppen-ID
			message.size = 3;
			canix_frame_send_with_prio(&message, HCAN_PRIO_LOW);

			canix_sleep_100th(10); // 100msec Pause
		}
		wdt_reset();
	}

	// Reedkontakte zaehlen:
	n_reed_open = 0;
	for (i = 0; i < 24; i++)
	{
		if ((fenster_monitor_reed_state[i]) && 
				(fenster_monitor_reed_state[i] != 255))
			n_reed_open++;
	}

	return n_reed_open;
}
Пример #14
0
/**
 * Fragt alle konfigurierten Reedkontakte nach ihrem Status und sammelt
 * die Ergebnisse in monitor_reedkontakt_state
 */
static void init_monitor_reedkontakt_request_states(void)
{
	eds_block_p it = eds_find_next_block((eds_block_p)0, EDS_userpanel_reedkontakte_BLOCK_ID);
	if (!it)
	{
		load_error_page(ERROR_CONF_REEDKONTAKTE_MISSING);
		reedkontakt_configured = 0;
		return;
	}

	userpanel_reedkontakte_t c;
	eeprom_read_block(&c, (it+2), sizeof(c));
	uint8_t i;

	// Ergebnis-Array initialisieren:
	for (i = 0; i < 24; i++)
		monitor_reedkontakt_state[i] = 255;

	// ueber alle Reedkontakte iterieren:
	for (i = 0; i < 24; i++)
	{
		if (c.reed[i] != 255) // ist es ein konfigurierter Reedkontakt?
		{
			// Nach Kontakt-Status fragen; die Ergebnisse kommen asynchron
			// ueber den CAN Handler rein
			canix_frame message;
			message.src = canix_selfaddr();
			message.dst = HCAN_MULTICAST_CONTROL;
			message.proto = HCAN_PROTO_SFP;
			message.data[0] = HCAN_SRV_HES;
			message.data[1] = HCAN_HES_REEDKONTAKT_STATE_QUERY;
			message.data[2] = c.reed[i]; // die Reedkontakt-Gruppen-ID
			message.size = 3;
			canix_frame_send_with_prio(&message, HCAN_PRIO_LOW);

			canix_sleep_100th(10); // 100msec Pause
		}
		wdt_reset();
	}
}
Пример #15
0
static inline void sendMessage(device_data_powerportAutomat *p, uint8_t active)
{
	canix_frame message;

	// Helligkeitssensor:
	if(	p->automatikEin // Automatikbetrieb
		&& (HCAN_HES_POWER_GROUP_ON == active) // HCAN_HES_POWER_GROUP_OFF soll immer moeglich sein
		&& (p->brightness != 65535) // Helligkeitssensor verwenden?
		&& (p->brightness > p->config.helligkeitsschwelle) ) // zu hell?
	{
		return; // zu hell -> kein HCAN_HES_POWER_GROUP_ON senden
	}

	message.src = canix_selfaddr();
	message.dst = HCAN_MULTICAST_CONTROL;
	message.proto = HCAN_PROTO_SFP;
	message.data[0] = HCAN_SRV_HES;
	message.data[1] = active; // HCAN_HES_POWER_GROUP_ON oder HCAN_HES_POWER_GROUP_OFF
	message.data[2] = p->config.powerport_gruppe;
	message.size = 3;
	canix_frame_send_with_prio(&message, HCAN_PRIO_HI);
}
Пример #16
0
/** Der helligkeitssensor_timer_handler wird alle 1 s aufgerufen: Er liest den ADC-Wert des
 *  konfigurierten helligkeitssensors und sendet diesen auf den CAN-Bus. */
inline void helligkeitssensor_timer_handler(device_data_helligkeitssensor *p, uint8_t zyklus)
{		
	if (zyklus != 1) return; // 1s-Zyklus verwendet

	uint16_t currentADCaverage;
	
	if (p->secsUntilNextSend)
	{
		p->secsUntilNextSend--;

		// nur die letzten n Werte vorm Senden sind wichtig:
		if(p->secsUntilNextSend <= SIZE_OF_AVG)
		{
			setADMUX(p->config.port);
			addToFloatAvg(&(p->filterBrightness), getADCvalue_inverted());
		}
	}
	else
	{
		currentADCaverage = getOutputValue(&(p->filterBrightness));

		// sende das Helligkeitssensortelegramm:
		canix_frame message;
		message.src = canix_selfaddr();
		message.dst = HCAN_MULTICAST_CONTROL;
		message.proto = HCAN_PROTO_SFP;
		message.data[0] = HCAN_SRV_HES;

		message.data[1] = HCAN_HES_HELLIGKEITS_INFO; //z.B. fuer rolladenAutomat-Device
		message.data[2] = p->config.gruppe;
		message.data[3] = (uint8_t)((currentADCaverage & 0xFF00) >> 8); //high value
		message.data[4] = (uint8_t)currentADCaverage; //low value
		message.size = 5;
		canix_frame_send_with_prio(&message, HCAN_PRIO_LOW);

		p->secsUntilNextSend = (uint16_t) 60 * p->config.sendCycleMins;
	}
}
Пример #17
0
/**
 * Sendet Updates an alle Action-Gruppen
 */
void inform_action_groups(const device_data_lichtzone *p)
{
	canix_frame answer;
	uint8_t *action_group;
	uint8_t i;

	action_group = (uint8_t *)&(p->config.action_gruppe0);

	for (i = 0; i < 2; i++)
	{
		if (action_group[i] != 255)
		{
			answer.src = canix_selfaddr();
			answer.dst = HCAN_MULTICAST_CONTROL;
			answer.proto = HCAN_PROTO_SFP;
			answer.data[0] = HCAN_SRV_HES;
			answer.data[1] = p->state != 0 ? HCAN_HES_POWER_GROUP_ON : HCAN_HES_POWER_GROUP_OFF;
			answer.data[2] = action_group[i];
			answer.size = 3;
			canix_frame_send_with_prio(&answer, HCAN_PRIO_HI);
		}
	}
}
Пример #18
0
inline void taster_timer_handler(device_data_taster *p, uint8_t zyklus)
{
    if (zyklus != 100) return; // 100tel-Sekunden-Zyklus verwendet

    canix_frame message;
    uint8_t time;

    // Wenn Taste gedrueckt ist, dann ist der Pin 0, ansonsten 1
    uint8_t status = ! tasterport_read(p->config.port);

    // Message schon mal vorbereiten:
    message.src = canix_selfaddr();
    message.dst = HCAN_MULTICAST_CONTROL;
    message.proto = HCAN_PROTO_SFP;
    message.data[0] = HCAN_SRV_HES;
    // message.data[1] wird unten ausgefuellt
    message.data[2] = p->config.gruppe;
    // message.data[3] wird unten ausgefuellt
    message.size = 4;

    if (status) // gedrueckt
    {
        // Entprellschutz:
        if (p->pressed < 255)
            p->pressed++;
    }
    else
    {
        // Wenn Schalter-Down schon gesendet wurde,
        // dann ein Schalter-Up Event senden:
        if (p->pressed > 3)
        {
            // ...und kein Flankenbetrieb konfiguriert ist:
            if (p->config.feature &
                    ((1<<FEATURE_TASTER_ROLLADEN_ZU)
                     | (1<<FEATURE_TASTER_ROLLADEN_AUF)) )
            {
                message.data[1] = HCAN_HES_ROLLADEN_POSITION_SET;
                message.data[3] = 222; // "Taster up" im Rolladen 2-Taster-Betrieb
                canix_frame_send_with_prio(&message, HCAN_PRIO_HI);
            }
            else if ( !(p->config.feature &
                        ((1<<FEATURE_TASTER_POWERPORT_AN)
                         | (1<<FEATURE_TASTER_POWERPORT_AUS)  )) )
            {
                message.data[1] = HCAN_HES_TASTER_UP;
                message.data[3] = p->config.port;
                canix_frame_send_with_prio(&message, HCAN_PRIO_HI);
            }
        }

        p->pressed = 0; // Taste wurde losgelassen, also Zaehler zuruecksetzen
    }

    if (p->config.feature & (1<<FEATURE_TASTER_ENTPRELL_1S))
        time = 100;
    else
        time = 3;

    if (p->pressed == time) // mind. 30msec gedrueckt
    {
        if (p->config.feature & (1<<FEATURE_TASTER_ROLLADEN_ZU))
        {
            message.data[1] = HCAN_HES_ROLLADEN_POSITION_SET;
            message.data[3] = 200; // gewuenschte Rollladenposition: Pos=200=0%=zu
        }
        else if (p->config.feature & (1<<FEATURE_TASTER_ROLLADEN_AUF))
        {
            message.data[1] = HCAN_HES_ROLLADEN_POSITION_SET;
            message.data[3] = 201; // gewuenschte Rollladenposition: Pos=201=100%=auf
        }
        else if (p->config.feature & (1<<FEATURE_TASTER_POWERPORT_AN))
        {
            message.data[1] = HCAN_HES_POWER_GROUP_ON;
            message.size = 3;
        }
        else if (p->config.feature & (1<<FEATURE_TASTER_POWERPORT_AUS))
        {
            message.data[1] = HCAN_HES_POWER_GROUP_OFF;
            message.size = 3;
        }
        else // kein z.B. Rollladentaster im 2-Tasterbetrieb
        {
            message.data[1] = HCAN_HES_TASTER_DOWN;
            message.data[3] = p->config.port;
        }

        canix_frame_send_with_prio(&message, HCAN_PRIO_HI);
    }
}
Пример #19
0
void canix_frame_send(const canix_frame *frame)
{
	canix_frame_send_with_prio(frame, HCAN_PRIO_LOW);
}
Пример #20
0
void powerport_page_handle_key_down_event(eds_powerport_page_block_t *p, 
		uint8_t key)
{
	if (key == KEY_OK)
	{
		if ((powerport_page_state == 1) && (powerport_page_timer > 0))
		{
			// Powerport ist eingeschaltet und der Timer laeuft; in diesem
			// Fall schaltet die OK Taste den Timer aus, laesst aber den
			// Powerport an
			//
			canix_frame message;

			message.src = canix_selfaddr();
			message.dst = HCAN_MULTICAST_CONTROL;
			message.proto = HCAN_PROTO_SFP;
			message.data[0] = HCAN_SRV_HES;
			message.data[1] = HCAN_HES_POWER_GROUP_SET_TIMER;
			message.data[2] = p->gruppe;
			message.data[3] = 0;
			message.data[4] = 0;
			message.size = 5;
			canix_frame_send_with_prio(&message, HCAN_PRIO_HI);

			lcdctrl_blink();
			canix_sleep_100th(5);
			powerport_page_print_page(p);

			return;

		}

		// Wenn der Powerport ein oder aus ist:
		if (powerport_page_state != -1)
		{
			canix_frame message;

			message.src = canix_selfaddr();
			message.dst = HCAN_MULTICAST_CONTROL;
			message.proto = HCAN_PROTO_SFP;
			message.data[0] = HCAN_SRV_HES;
			message.data[1] = powerport_page_state ? 
				HCAN_HES_POWER_GROUP_OFF : HCAN_HES_POWER_GROUP_ON;
			message.data[2] = p->gruppe;
			message.size = 3;
			canix_frame_send_with_prio(&message, HCAN_PRIO_HI);

			lcdctrl_blink();
			canix_sleep_100th(5);
			powerport_page_print_page(p);

			return;
		}
	}

	if (key == KEY_ESC)
	{
		goto_page_up();
		return;
	}

	if (key == KEY_UP)
		goto_prev_page();

	if (key == KEY_DOWN)
		goto_next_page();
}
Пример #21
0
/** multitaster_timer_handler sendet eine Taster UP-/DOWN-Nachricht
 *  auf den CAN-Bus. Der multitaster_timer_handler wird alle 10msec aufgerufen. */ 
void multitaster_timer_handler(device_data_multitaster *p)
{
	canix_frame message;
	uint8_t time;

	// Wenn Taste gedrueckt ist, dann ist der Pin 0, ansonsten 1
	uint8_t status = ! tasterport_read(p->config.taster_port);

	// Message schon mal vorbereiten:
	message.src = canix_selfaddr();
	message.dst = HCAN_MULTICAST_CONTROL;
	message.proto = HCAN_PROTO_SFP;
	message.data[0] = HCAN_SRV_HES;
	// message.data[1] wird unten ausgefuellt
	message.data[2] = getGroup(p);
	// message.data[3] wird unten ausgefuellt
	message.size = 4;

	if (status) // gedrueckt
	{
		// Entprellschutz:
		if (p->pressed < 255)
			p->pressed++;
	}
	else
	{
		// Wenn Schalter-Down schon gesendet wurde,
		// dann ein Schalter-Up Event senden:
		if (p->pressed > 3)
		{
			//...und kein Rollladentaster im 2-Tasterbetrieb konfiguriert ist:
			if ( !(p->config.feature & ((1<<FEATURE_MULTITASTER_ROLLADEN_ZU) | (1<<FEATURE_MULTITASTER_ROLLADEN_AUF))) )
			{
				message.data[1] = HCAN_HES_TASTER_UP;
				message.data[3] = p->config.taster_port;
				canix_frame_send_with_prio(&message, HCAN_PRIO_HI);
			}
		}

		// Taste wurde losgelassen, also Zaehler zuruecksetzen
		p->pressed = 0;
	}

	if (p->config.feature & (1<<FEATURE_MULTITASTER_ENTPRELL_1S))
		time = 100;
	else
		time = 3;

	
	if (p->pressed == time) // mind. 30msec gedrueckt
	{
		if (p->config.feature & (1<<FEATURE_MULTITASTER_ROLLADEN_ZU))
		{
			message.data[1] = HCAN_HES_ROLLADEN_POSITION_SET;
			message.data[3] = 200; //gewuenschte Rollladenposition: Pos=200=0%=zu
		}
		else if (p->config.feature & (1<<FEATURE_MULTITASTER_ROLLADEN_AUF))
		{
			message.data[1] = HCAN_HES_ROLLADEN_POSITION_SET;
			message.data[3] = 201; //gewuenschte Rollladenposition: Pos=201=100%=auf
		}
		else //kein Rollladentaster im 2-Tasterbetrieb
		{
			message.data[1] = HCAN_HES_TASTER_DOWN;
			message.data[3] = p->config.taster_port;
		}
		
		canix_frame_send_with_prio(&message, HCAN_PRIO_HI);
	}
}
Пример #22
0
/**
 * this timer handler is called every second
 */
void heizung_timer_handler(device_data_heizung *p)
{
	if (p->ventilpflege_counter > 0)
		p->ventilpflege_counter--;

	// Ventilpflege aktivieren, falls der richtige Zeitpunkt dazu ist:
	heizung_check_ventilpflege(p);

	if (p->received_interval_counter != 0xff)
		p->received_interval_counter++;

	heizung_handle_pwm(p);

	if (p->duration_counter > 0)
	{
		p->duration_counter -= 1;
		if (p->duration_counter == 0)
		{
			// Zeit ist abgelaufen; nun wieder auf Automatik-Modus
			// stellen:
			//
			p->mode = HEIZUNG_MODE_AUTOMATIK;
		}
	}

	if (p->reed_heiz_stop_counter > 0)
	{	
		p->reed_heiz_stop_counter -= 1;

		if (p->reed_heiz_stop_counter == 0)
		{
			canix_syslog_P(SYSLOG_PRIO_DEBUG,
					PSTR("heiz-stop ende (heizung %d)"), p->config.id);
		}
	}

	/*
	 * Schaltet die HK-Ventile aus, wenn ein Heizstop vorliegt. Dies passiert
	 * in regelmaessigen Abstaenden, da eventuell aufgrund der Heizsteuerlogik
	 * die PWM nicht regelmaessig upgedatet wird und so das HK-Ventil nicht auf
	 * den Reedkontakt reagiert.
	 */
	heizung_update_heizstop(p);

	if (p->timer_counter++ >= 5)
	{
		p->timer_counter = 0;

		switch (p->mode)
		{
			case HEIZUNG_MODE_OFF : 
				{
					if (p->ventilpflege_counter)
					{
						// Sonderfall: Ventilpflege ist aktiv; dazu
						// Ventil einschalten, sonst aber nichts
						// unternehmen:
						
						p->manual_rate = 0;

						// Ventil einschalten:
						heizung_set_pwm(p,100);
						darlingtonoutput_setpin(p->config.port, 1);

						canix_syslog_P(SYSLOG_PRIO_DEBUG, 
								PSTR("ventilpflege: 1"));
					}
					else
					{
						// das ist Normalfall: keine Ventilpflege aktiv.
						p->manual_rate = 0;
						heizung_set_pwm(p,0);

						// Ventil ausschalten, falls es an ist:
						if (darlingtonoutput_getpin(p->config.port))
							darlingtonoutput_setpin(p->config.port, 0);
					}
					return;
				}
			case HEIZUNG_MODE_MANUAL :
				{
					heizung_set_pwm(p, p->manual_rate);
				}
				break;
			case HEIZUNG_MODE_AUTOMATIK :
				{
					// Wenn ein gueltiger Messwert vorliegt
					// (d.h. wenn innerhalb eines definierten Zeitraumes
					// ein Sensor-Messwert eingetroffen ist:
					if (p->received_interval_counter < 255)
					{
						int8_t index;
						index = heizung_get_matching_zeitzone_index(p);
						if (index != -1)
						{
							// we got an zeitzone which matches
							solltemp_line_t *solltemp_line = (solltemp_line_t*) 
								&(p->config.zeitzone0_id);
							heizung_set_pwm_by_temp(p, 
									solltemp_line[index].temp,
									p->measure_value);
						}
						else
						{
							// keine passende Zeitzone gefunden
							heizung_set_pwm(p,0);
						}
					}
					else
					{
						canix_syslog_P(SYSLOG_PRIO_ERROR, 
								PSTR("keine Sensor-Messwerte vorhanden!"));
					}
				}
				break;
			case HEIZUNG_MODE_THERMOSTAT :
				{
					// Wenn ein gueltiger Messwert vorliegt
					// (d.h. wenn innerhalb eines definierten Zeitraumes
					// ein Sensor-Messwert eingetroffen ist:
					if (p->received_interval_counter < 255)
					{
						heizung_set_pwm_by_temp(p, p->thermostat_temp,
								p->measure_value);
					}
					else
					{
						canix_syslog_P(SYSLOG_PRIO_ERROR, 
								PSTR("keine Sensor-Messwerte vorhanden!"));
					}
				}
				break;
		}
	}

	// Waermebedarfsmeldung versenden:
	if (p->waermebedarf_counter-- == 0)
	{
		canix_frame message;

		// Waermebedarfsmeldungen alle 60 Sekunden
		p->waermebedarf_counter = 60;

		// den aktuellen Ventilstand / Heizrate ermitteln:
		uint8_t rate = heizung_get_pwm(p);

		// Feature-Bit testen, und ggfls Waermebedarf verdoppeln:
		if (p->config.feature & (1<<HEIZUNG_FEATURE_DOPPEL_WAERMEBEDARF))
			rate = rate << 1;

		// Der Waermebedarf ist proportional zur Ventilstellung, d.h.
		// der Bedarf ist hoch, wenn das Ventil voll offen ist, und ist
		// nicht vorhanden, wenn das Ventil zu ist.

		message.src = canix_selfaddr();
		message.dst = HCAN_MULTICAST_INFO;
		message.proto = HCAN_PROTO_SFP;
		message.data[0] = HCAN_SRV_HES;
		message.data[1] = HCAN_HES_HEIZUNG_WAERMEBEDARF_INFO;
		message.data[2] = p->config.id;
		message.data[3] = rate;
		message.size = 4;

		canix_frame_send_with_prio(&message, HCAN_PRIO_LOW);
	}
}
Пример #23
0
void rolladen_can_callback(device_data_rolladen *p, const canix_frame *frame)
{
	canix_frame answer;

	answer.src = canix_selfaddr();
	answer.dst = frame->src;
	answer.proto = HCAN_PROTO_SFP;
	answer.data[0] = HCAN_SRV_HES;

	switch (frame->data[1])
	{
		case HCAN_HES_ROLLADEN_POSITION_SET:
			if (is_group_in_rolladen(p, frame->data[2]))
			{
				switch (frame->data[3])
				{
					case 200: // Taster-Down im 2-Taster-Betrieb: ZU = 0 %
						if (p->mute || p->blockingTimer) return; // Befehl abblocken

						if (p->power || p->soll_power)
							rolladen_cmd_stop (p); // anhalten, falls der Rolladen faehrt
						else if (set_soll_laufzeit(p, ROLLADEN_DIR_AB))
						{
							// noch nicht in soll-Position:
							p->long_pressed_counter = 10; // 1 s
							rolladen_cmd_drive (p);
						}
						break;

					case 201: // Taster-Down im 2-Taster-Betrieb: AUF = 100 %
						if (p->mute || p->blockingTimer) return; // Befehl abblocken

						if (p->power || p->soll_power)
							rolladen_cmd_stop (p); // anhalten, falls der Rolladen faehrt
						else if (set_soll_laufzeit(p, ROLLADEN_DIR_AUF)) // noch nicht in soll-Position?
						{
							// noch nicht in soll-Position:
							p->long_pressed_counter = 10; // 1 s
							rolladen_cmd_drive (p);
						}
						break;

					case 202: // HALT ueber Web-Interface
						p->long_pressed_counter = -1; // abmelden (2-Taster-Betrieb)
						rolladen_cmd_stop (p);
						break;

					case 222: // Taster-Up im 2-Taster-Betrieb
						p->long_pressed_counter = -1; // abmelden
						break;

					default: // frame->data[3] = Positionsvorgabe in %
						if (p->mute || p->blockingTimer) return; // Befehl abblocken

						p->soll_laufzeit = (int32_t)p->config.laufzeit * frame->data[3] / 100;
						canix_syslog_P(SYSLOG_PRIO_DEBUG, PSTR("s %d"), p->soll_laufzeit);
						if (p->soll_laufzeit < 0) p->soll_laufzeit = 0;
						if (p->soll_laufzeit > p->config.laufzeit) p->soll_laufzeit = p->config.laufzeit;

						if (p->power || p->soll_power || p->soll_laufzeit == p->laufzeit)
						{
							p->soll_laufzeit = -1;
							return; // ignorieren, falls der Rolladen faehrt  oder  die Soll-Pos. schon hat
						}

						p->kalibrieren = 0; // nicht kalibrieren
						if (p->soll_laufzeit < p->laufzeit)	p->soll_dir = ROLLADEN_DIR_AB;
						else p->soll_dir = ROLLADEN_DIR_AUF;
						rolladen_cmd_drive (p);
				}
			}
			break;

		case HCAN_HES_TASTER_DOWN: // Nur im 1-Taster-Betrieb verwendet
			if (is_group_in_rolladen(p, frame->data[2]))
			{
				if (p->mute || p->blockingTimer) return; // Befehl abblocken

				if (p->power)
				{
					p->change_dir_counter = 7; // 0,7 s (1-Taster-Betrieb: Richtungswechsel, falls lange gedrueckt)
					rolladen_cmd_stop (p); // anhalten, falls der Rolladen faehrt
				}
				else
				{
					set_soll_laufzeit(p, p->last_dir);
					if (p->soll_laufzeit != -1) // liegt soll-Position bereits vor?
						rolladen_cmd_drive (p);
				}
			}
			break;

		case HCAN_HES_TASTER_UP: // Nur im 1-Taster-Betrieb verwendet
			if (is_group_in_rolladen(p, frame->data[2]))
				p->change_dir_counter = -1; // abmelden (1-Taster-Betrieb)
			break;

		case HCAN_HES_ROLLADEN_DEFINE_POSITION:
			{
				// Da die Rolladen keine Rueckmeldung geben, wo sie
				// gerade stehen, kann im Service-Falle (z.B. bei einem
				// Firmware Upgrade die Position der Rollaeden vorher
				// mit HCAN_HES_ROLLADEN_POSITION_REQUEST erfragt und
				// nach dem Upgrade mit HCAN_HES_ROLLADEN_DEFINE_POSITION
				// definiert werden.

				if (is_group_in_rolladen(p, frame->data[2]))
				{
					// Rolladenposition setzen: (pos+1) wegen Rundungsfehler
					p->laufzeit = (int32_t)(frame->data[3]+1) * p->config.laufzeit / 100;

					if (p->laufzeit > p->config.laufzeit) p->laufzeit = p->config.laufzeit;
				}
			}
			break;

		case HCAN_HES_ROLLADEN_POSITION_REQUEST:
			if (is_group_in_rolladen(p, frame->data[2]))
			{
				answer.data[1] = HCAN_HES_ROLLADEN_POSITION_REPLAY;
				answer.data[2] = frame->data[2];
				answer.data[3] = rolladen_get_position(p);
				answer.size = 4;
				canix_frame_send_with_prio(&answer, HCAN_PRIO_HI);
			}
			break;
	}

	if (p->config.mute == frame->data[2])
	{
		if (HCAN_HES_MUTE_OFF == frame->data[1])
			p->mute = 0; // Rolladen aktiv
		else if (HCAN_HES_MUTE_ON == frame->data[1])
			p->mute = 1; // Rolladen passiv (per Taster nicht verfahrbar)
	}
}
Пример #24
0
void heizung_can_callback(device_data_heizung *p, const canix_frame *frame)
{
	canix_frame answer;

	answer.src = canix_selfaddr();
	answer.dst = frame->src;
	answer.proto = HCAN_PROTO_SFP;
	answer.data[0] = HCAN_SRV_HES;

	switch (frame->data[1])
	{
		case HCAN_HES_1WIRE_TEMPERATURE :
			if (frame->data[2] == p->config.sensor_id)
			{
				// we have a heizung and a temp sensor frame
				// now look if if fits to the heizung

				// temperature is a fixed point number mit 4 LSB Bits
				int16_t sensor_temp = frame->data[3] << 8 | 
					frame->data[4];

				// store the measure value
				p->measure_value = sensor_temp;
				p->received_interval_counter = 0;
			}
			break;

		case HCAN_HES_HEIZUNG_SET_MODE_OFF :
			if (p->config.id == frame->data[2])
				p->mode = HEIZUNG_MODE_OFF;
			break;

		case HCAN_HES_HEIZUNG_SET_MODE_MANUAL :
			if (p->config.id == frame->data[2])
			{
				p->mode = HEIZUNG_MODE_MANUAL;
				p->manual_rate = frame->data[3];
				p->duration_counter = (frame->data[4] << 8) | frame->data[5];
			}
			break;

		case HCAN_HES_HEIZUNG_SET_MODE_THERMOSTAT_DETAILS :
			if (p->config.id == frame->data[2])
			{
				p->mode = HEIZUNG_MODE_THERMOSTAT;
				p->thermostat_temp = (frame->data[3] << 8) | frame->data[4];
				p->duration_counter = (frame->data[5] << 8) | frame->data[6];
			}
			break;

		case HCAN_HES_HEIZUNG_SET_MODE_AUTOMATIK:
			if (p->config.id == frame->data[2])
				p->mode = HEIZUNG_MODE_AUTOMATIK;
			break;

		case HCAN_HES_HEIZUNG_DETAILS_REQUEST :
			{
				if (p->config.id == frame->data[2])
				{
					switch (p->mode)
					{
						case HEIZUNG_MODE_OFF :
							answer.data[1] = 
								HCAN_HES_HEIZUNG_MODE_OFF_DETAILS;
							answer.data[2] = p->config.id;
							answer.size = 3;
							canix_frame_send_with_prio(&answer, HCAN_PRIO_HI);
							break;

						case HEIZUNG_MODE_MANUAL :
							answer.data[1] = 
								HCAN_HES_HEIZUNG_MODE_MANUAL_DETAILS;
							answer.data[2] = p->config.id;
							answer.data[3] = p->manual_rate;
							answer.data[4] = p->duration_counter >> 8;
							answer.data[5] = p->duration_counter;
							answer.size = 6;
							canix_frame_send_with_prio(&answer, HCAN_PRIO_HI);
							break;

						case HEIZUNG_MODE_THERMOSTAT :
							answer.data[1] = 
								HCAN_HES_HEIZUNG_MODE_THERMOSTAT_DETAILS;
							answer.data[2] = p->config.id;
							answer.data[3] = p->thermostat_temp >> 8;
							answer.data[4] = p->thermostat_temp;
							answer.data[5] = p->duration_counter >> 8;
							answer.data[6] = p->duration_counter;
							answer.size = 7;
							canix_frame_send_with_prio(&answer, HCAN_PRIO_HI);
							break;

						case HEIZUNG_MODE_AUTOMATIK :
							{
								int8_t index;
								index = heizung_get_matching_zeitzone_index(p);
								if (index != -1)
								{
									// we got an zeitzone which matches
									int16_t master_value = 0;
									solltemp_line_t *zeitzone = 
										(solltemp_line_t *) 
										&(p->config.zeitzone0_id);

									master_value = zeitzone[index].temp;
									answer.data[1] = 
										HCAN_HES_HEIZUNG_MODE_AUTOMATIK_DETAILS;
									answer.data[2] = frame->data[2];
									answer.data[3] = master_value >> 8;
									answer.data[4] = master_value;
									answer.data[5] = 
										heizung_get_matching_zeitzone_id(p);
									answer.size = 6;
								}
								else
								{
									canix_syslog_P(SYSLOG_PRIO_ERROR,
											PSTR("zeitzone: no match!"));

									answer.data[1] = 
										HCAN_HES_HEIZUNG_MODE_AUTOMATIK_DETAILS;
									answer.data[2] = frame->data[2];
									answer.data[3] = 0;
									answer.data[4] = 0;
									answer.data[5] = 0;
									answer.size = 6;
								}
								canix_frame_send_with_prio(&answer, 
										HCAN_PRIO_HI);
							}
							break;
					}
				}
			}
Пример #25
0
void lichtzone_can_callback(device_data_lichtzone *p, 
		const canix_frame *frame)
{
	switch (frame->data[1])
	{
		case HCAN_HES_TASTER_DOWN : 
			{
				uint8_t i;
				uint8_t *toggle_group;
				uint8_t *off_group;
				uint8_t *on_group;

				// fuer extended on Modus:
				if (p->exton_sec_counter == 0)
				{
					p->exton_sec_counter = 1;
				}
				p->exton_taster_down_counter++;

				// ueber alle 4 Toggle Gruppen iterieren
				toggle_group = (uint8_t *) &(p->config.toggle_gruppe0);
				for (i = 0; i < 4; i++)
				{
					if (frame->data[2] == toggle_group[i])
					{
						// Pruefen, ob in den ext on Modus geschaltet werden soll:
						if ((p->exton_taster_down_counter >= 3) && 
								(p->exton_sec_counter > 0) &&
								(p->exton_sec_counter < LICHTZONE_EXT_SEC_COUNTER_MAX))
						{
							p->exton_sec_counter = 0;
							p->exton_taster_down_counter = 0;
							p->state = LICHTZONE_STATE_ON_EXT;
							p->timer_counter = LICHTZONE_EXT_TIMERINIT;
							inform_action_groups(p);
							// ganz rausspringen, damit innerhalb der naechsten Interation der Schleife
							// nicht den State wieder zurueckgestetzt wird!
							return;
						}

						// Normaler Modus: wenn Timer aktiviert...
						if (p->config.timer_delay)
						{
							switch (p->state)
							{
								case LICHTZONE_STATE_OFF :
									lichtzone_setup_timer(p);
									p->state = LICHTZONE_STATE_ON;
									inform_action_groups(p);
									break;
								case LICHTZONE_STATE_ON : 
									lichtzone_setup_timer(p);
									break;
								case LICHTZONE_STATE_ON_EXT : 
									p->state = LICHTZONE_STATE_OFF;
									p->exton_sec_counter = 0;
									p->exton_taster_down_counter = 0;
									p->timer_counter = 0;
									inform_action_groups(p);
									break;
							}
						}
						// Normaler Modus: wenn kein Timer aktiviert...
						else
						{
							switch (p->state)
							{
								case LICHTZONE_STATE_OFF :
									p->state = LICHTZONE_STATE_ON;
									break;
								case LICHTZONE_STATE_ON : 
									p->state = LICHTZONE_STATE_OFF;
									break;
								case LICHTZONE_STATE_ON_EXT : 
									p->state = LICHTZONE_STATE_OFF;
									break;
							}

							inform_action_groups(p);
						}
					}
				}

				// wenn eine Off-Gruppe passt, die Action Gruppen
				// informieren. Das geschieht unabhaengig vom Status;
				// denn damit ist eine globale Haus-Licht-Aus-Funktion
				// realisierbar
				off_group = (uint8_t *) &(p->config.off_gruppe0);
				for (i = 0; i < 2; i++)
				{
					if ((frame->data[2] == off_group[i]))
					{
						p->state = LICHTZONE_STATE_OFF;
						p->timer_counter = 0;
						inform_action_groups(p);
					}
				}

				// wenn eine On-Gruppe passt, die Action Gruppen
				// informieren. Das geschieht unabhaengig vom Status;
				// denn damit ist eine globale Haus-Licht-An-Funktion
				// realisierbar
				on_group = (uint8_t *) &(p->config.on_gruppe0);
				for (i = 0; i < 2; i++)
				{
					if ((frame->data[2] == on_group[i]))
					{
						p->state = LICHTZONE_STATE_ON;

						// If it has a timer, reset the timer:
						if (p->config.timer_delay) 
							lichtzone_setup_timer(p);

						inform_action_groups( p);
					}
				}
			}
			break;

		case HCAN_HES_POWER_GROUP_ON : 
			{
				// schauen, ob eine der Action Groups passt; falls
				// ja, internen Status updaten und ggfls Timer starten
				uint8_t *action_group;
				uint8_t i;

				action_group = (uint8_t *)&(p->config.action_gruppe0);

				for (i = 0; i < 2; i++)
				{
					if ((action_group[i] != 255) && 
							(action_group[i] == frame->data[2]))
					{
						switch (p->state)
						{
							case LICHTZONE_STATE_OFF :
							case LICHTZONE_STATE_ON :
								p->state = LICHTZONE_STATE_ON;
								if (p->config.timer_delay)
									lichtzone_setup_timer(p);
								// inform_action_groups(..) entfaellt, da
								// wir ja eine Botschaft, die direkt an die
								// Action group ging, abgefangen haben. Daher
								// haben wir "nur" den State aktualisiert.
								break;
							case LICHTZONE_STATE_ON_EXT :
								// in diesem Falls nichts machen!
								break;
						}
					}
				}
			}
			break;

		case HCAN_HES_POWER_GROUP_OFF : 
			{
				// schauen, ob eine der Action Groups passt; falls
				// ja, internen Status updaten
				uint8_t *action_group;
				uint8_t i;

				action_group = (uint8_t *)&(p->config.action_gruppe0);

				for (i = 0; i < 2; i++)
				{
					if ((action_group[i] != 255) && 
							(action_group[i] == frame->data[2]))
					{
						p->state = LICHTZONE_STATE_OFF;
						p->timer_counter = 0;

						// inform_action_groups(..) entfaellt, da
						// wir ja eine Botschaft, die direkt an die
						// Action group ging, abgefangen haben. Daher
						// haben wir "nur" den State aktualisiert.
						
						break;
					}
				}
			}
			break;

		case HCAN_HES_POWER_GROUP_TIMER_QUERY : 
			{
				canix_frame answer;
				uint8_t *action_group;
				uint8_t i;

				action_group = (uint8_t *)&(p->config.action_gruppe0);

				for (i = 0; i < 2; i++)
				{
					if (action_group[i] == frame->data[2])
					{
						answer.src = canix_selfaddr();
						answer.dst = frame->src;
						answer.proto = HCAN_PROTO_SFP;
						answer.data[0] = HCAN_SRV_HES;
						answer.data[1] = HCAN_HES_POWER_GROUP_TIMER_REPLAY;
						answer.data[2] = action_group[i];
						answer.data[3] = p->timer_counter >> 8;
						answer.data[4] = p->timer_counter & 0xff;
						answer.size = 5;
						canix_frame_send_with_prio(&answer, HCAN_PRIO_HI);
						break;
					}
				}
			}
			break;

		case HCAN_HES_POWER_GROUP_SET_TIMER : 
			{
				uint8_t *action_group;
				uint8_t i;

				action_group = (uint8_t *)&(p->config.action_gruppe0);

				for (i = 0; i < 2; i++)
				{
					if (action_group[i] == frame->data[2])
					{
						p->timer_counter = (frame->data[3] << 8) |
							frame->data[4];
						break;
					}
				}
			}
			break;

	}