void receive_message(HNDLE hBuf, HNDLE id, EVENT_HEADER * header, void *message) { char str[256], *pc, *sp; static DWORD last_beep = 0; /* print message */ printf("%s\n", (char *) (message)); if (fp == NULL) { fputs("Speech synthesizer not enabled - terminating\n", stderr); cm_disconnect_experiment(); exit(2); } /* skip none talking message */ if (header->trigger_mask == MT_TALK || header->trigger_mask == MT_USER) { pc = strchr((char *) (message), ']') + 2; sp = pc + strlen(pc) - 1; while (*sp == ' ' || *sp == '\t') sp--; *(++sp) = '\0'; /* Send beep first */ // "play --volume=0.3 /etc/mt_talk.wav" if ((ss_time() - last_beep) > shutupTime) { switch (header->trigger_mask) { case MT_TALK: if (mtTalkStr[0]) sprintf(str, "%s", mtTalkStr); break; case MT_USER: if (mtUserStr[0]) sprintf(str, "%s", mtUserStr); break; } ss_system(str); last_beep = ss_time(); ss_sleep(1000); } #ifdef OS_DARWIN sprintf(str, "say %s.", pc); ss_system(str); #else fprintf(fp, "%s.\n", pc); fflush(fp); #endif } return; }
/** Scan ODB for alarms. @return AL_SUCCESS */ INT al_check() { if (rpc_is_remote()) return rpc_call(RPC_AL_CHECK); #ifdef LOCAL_ROUTINES { INT i, status, size, semaphore; HNDLE hDB, hkeyroot, hkey; KEY key; ALARM a; char str[256], value[256]; time_t now; PROGRAM_INFO program_info; BOOL flag; ALARM_CLASS_STR(alarm_class_str); ALARM_ODB_STR(alarm_odb_str); ALARM_PERIODIC_STR(alarm_periodic_str); cm_get_experiment_database(&hDB, NULL); if (hDB == 0) return AL_SUCCESS; /* called from server not yet connected */ /* check online mode */ flag = TRUE; size = sizeof(flag); db_get_value(hDB, 0, "/Runinfo/Online Mode", &flag, &size, TID_INT, TRUE); if (!flag) return AL_SUCCESS; /* check global alarm flag */ flag = TRUE; size = sizeof(flag); db_get_value(hDB, 0, "/Alarms/Alarm system active", &flag, &size, TID_BOOL, TRUE); if (!flag) return AL_SUCCESS; /* request semaphore */ cm_get_experiment_semaphore(&semaphore, NULL, NULL, NULL); status = ss_semaphore_wait_for(semaphore, 100); if (status == SS_TIMEOUT) return AL_SUCCESS; /* someone else is doing alarm business */ if (status != SS_SUCCESS) { printf("al_check: Something is wrong with our semaphore, ss_semaphore_wait_for() returned %d, aborting.\n", status); //abort(); // DOES NOT RETURN printf("al_check: Cannot abort - this will lock you out of odb. From this point, MIDAS will not work correctly. Please read the discussion at https://midas.triumf.ca/elog/Midas/945\n"); // NOT REACHED return AL_SUCCESS; } /* check ODB alarms */ db_find_key(hDB, 0, "/Alarms/Alarms", &hkeyroot); if (!hkeyroot) { /* create default ODB alarm */ status = db_create_record(hDB, 0, "/Alarms/Alarms/Demo ODB", strcomb(alarm_odb_str)); db_find_key(hDB, 0, "/Alarms/Alarms", &hkeyroot); if (!hkeyroot) { ss_semaphore_release(semaphore); return AL_SUCCESS; } status = db_create_record(hDB, 0, "/Alarms/Alarms/Demo periodic", strcomb(alarm_periodic_str)); db_find_key(hDB, 0, "/Alarms/Alarms", &hkeyroot); if (!hkeyroot) { ss_semaphore_release(semaphore); return AL_SUCCESS; } /* create default alarm classes */ status = db_create_record(hDB, 0, "/Alarms/Classes/Alarm", strcomb(alarm_class_str)); status = db_create_record(hDB, 0, "/Alarms/Classes/Warning", strcomb(alarm_class_str)); if (status != DB_SUCCESS) { ss_semaphore_release(semaphore); return AL_SUCCESS; } } for (i = 0;; i++) { status = db_enum_key(hDB, hkeyroot, i, &hkey); if (status == DB_NO_MORE_SUBKEYS) break; db_get_key(hDB, hkey, &key); size = sizeof(a); status = db_get_record(hDB, hkey, &a, &size, 0); if (status != DB_SUCCESS || a.type < 1 || a.type > AT_LAST) { /* make sure alarm record has right structure */ db_check_record(hDB, hkey, "", strcomb(alarm_odb_str), TRUE); size = sizeof(a); status = db_get_record(hDB, hkey, &a, &size, 0); if (status != DB_SUCCESS || a.type < 1 || a.type > AT_LAST) { cm_msg(MERROR, "al_check", "Cannot get alarm record"); continue; } } /* check periodic alarm only when active */ if (a.active && a.type == AT_PERIODIC && a.check_interval > 0 && (INT) ss_time() - (INT) a.checked_last > a.check_interval) { /* if checked_last has not been set, set it to current time */ if (a.checked_last == 0) { a.checked_last = ss_time(); db_set_record(hDB, hkey, &a, size, 0); } else al_trigger_alarm(key.name, a.alarm_message, a.alarm_class, "", AT_PERIODIC); } /* check alarm only when active and not internal */ if (a.active && a.type == AT_EVALUATED && a.check_interval > 0 && (INT) ss_time() - (INT) a.checked_last > a.check_interval) { /* if condition is true, trigger alarm */ if (al_evaluate_condition(a.condition, value)) { sprintf(str, a.alarm_message, value); al_trigger_alarm(key.name, str, a.alarm_class, "", AT_EVALUATED); } else { a.checked_last = ss_time(); status = db_set_value(hDB, hkey, "Checked last", &a.checked_last, sizeof(DWORD), 1, TID_DWORD); if (status != DB_SUCCESS) { cm_msg(MERROR, "al_check", "Cannot change alarm record"); continue; } } } } /* check /programs alarms */ db_find_key(hDB, 0, "/Programs", &hkeyroot); if (hkeyroot) { for (i = 0;; i++) { status = db_enum_key(hDB, hkeyroot, i, &hkey); if (status == DB_NO_MORE_SUBKEYS) break; db_get_key(hDB, hkey, &key); /* don't check "execute on xxx" */ if (key.type != TID_KEY) continue; size = sizeof(program_info); status = db_get_record(hDB, hkey, &program_info, &size, 0); if (status != DB_SUCCESS) { cm_msg(MERROR, "al_check", "Cannot get program info record"); continue; } now = ss_time(); rpc_get_name(str); str[strlen(key.name)] = 0; if (!equal_ustring(str, key.name) && cm_exist(key.name, FALSE) == CM_NO_CLIENT) { if (program_info.first_failed == 0) { program_info.first_failed = (DWORD) now; db_set_record(hDB, hkey, &program_info, sizeof(program_info), 0); } /* fire alarm when not running for more than what specified in check interval */ if (now - program_info.first_failed >= program_info.check_interval / 1000) { /* if not running and alarm calss defined, trigger alarm */ if (program_info.alarm_class[0]) { sprintf(str, "Program %s is not running", key.name); al_trigger_alarm(key.name, str, program_info.alarm_class, "Program not running", AT_PROGRAM); } /* auto restart program */ if (program_info.auto_restart && program_info.start_command[0]) { ss_system(program_info.start_command); program_info.first_failed = 0; cm_msg(MTALK, "al_check", "Program %s restarted", key.name); } } } else { if (program_info.first_failed != 0) { program_info.first_failed = 0; db_set_record(hDB, hkey, &program_info, sizeof(program_info), 0); } } } } ss_semaphore_release(semaphore); } #endif /* LOCAL_COUTINES */ return SUCCESS; }
INT al_trigger_class(const char *alarm_class, const char *alarm_message, BOOL first) /********************************************************************\ Routine: al_trigger_class Purpose: Trigger a certain alarm class Input: char *alarm_class Alarm class, must be defined in /alarms/classes char *alarm_message Optional message which goes with alarm BOOL first TRUE if alarm is triggered first time (used for elog) Output: Function value: AL_INVALID_NAME Alarm class not defined AL_SUCCESS Successful completion \********************************************************************/ { int status, size, state; HNDLE hDB, hkeyclass; char str[256], command[256], tag[32], url[256]; ALARM_CLASS ac; DWORD now = ss_time(); tag[0] = 0; cm_get_experiment_database(&hDB, NULL); /* get alarm class */ sprintf(str, "/Alarms/Classes/%s", alarm_class); db_find_key(hDB, 0, str, &hkeyclass); if (!hkeyclass) { cm_msg(MERROR, "al_trigger_class", "Alarm class %s not found in ODB", alarm_class); return AL_INVALID_NAME; } size = sizeof(ac); status = db_get_record(hDB, hkeyclass, &ac, &size, 0); if (status != DB_SUCCESS) { cm_msg(MERROR, "al_trigger_class", "Cannot get alarm class record"); return AL_ERROR_ODB; } /* write system message */ if (ac.write_system_message && (now - ac.system_message_last >= (DWORD)ac.system_message_interval)) { if (equal_ustring(alarm_class, "All")) sprintf(str, "General alarm: %s", alarm_message); else sprintf(str, "%s: %s", alarm_class, alarm_message); cm_msg(MTALK, "al_trigger_class", "%s", str); ac.system_message_last = now; } /* write elog message on first trigger if using internal ELOG */ size = sizeof(url); if (ac.write_elog_message && first && db_get_value(hDB, 0, "/Elog/URL", url, &size, TID_STRING, FALSE) != DB_SUCCESS) el_submit(0, "Alarm system", "Alarm", "General", alarm_class, str, "", "plain", "", "", 0, "", "", 0, "", "", 0, tag, sizeof(tag)); /* execute command */ if (ac.execute_command[0] && ac.execute_interval > 0 && (INT) ss_time() - (INT) ac.execute_last > ac.execute_interval) { if (equal_ustring(alarm_class, "All")) sprintf(str, "General alarm: %s", alarm_message); else sprintf(str, "%s: %s", alarm_class, alarm_message); sprintf(command, ac.execute_command, str); cm_msg(MINFO, "al_trigger_class", "Execute: %s", command); ss_system(command); ac.execute_last = ss_time(); } /* stop run */ if (ac.stop_run) { state = STATE_STOPPED; size = sizeof(state); db_get_value(hDB, 0, "/Runinfo/State", &state, &size, TID_INT, TRUE); if (state != STATE_STOPPED) { cm_msg(MINFO, "al_trigger_class", "Stopping the run from alarm class \'%s\', message \'%s\'", alarm_class, alarm_message); cm_transition(TR_STOP, 0, NULL, 0, TR_DETACH, FALSE); } } status = db_set_record(hDB, hkeyclass, &ac, sizeof(ac), 0); if (status != DB_SUCCESS) { cm_msg(MERROR, "al_trigger_class", "Cannot update alarm class record"); return AL_ERROR_ODB; } return AL_SUCCESS; }