kopia lustrzana https://github.com/cariboulabs/cariboulite
410 wiersze
12 KiB
C
410 wiersze
12 KiB
C
![]() |
#ifndef ZF_LOG_LEVEL
|
||
|
#define ZF_LOG_LEVEL ZF_LOG_VERBOSE
|
||
|
#endif
|
||
|
#define ZF_LOG_DEF_SRCLOC ZF_LOG_SRCLOC_LONG
|
||
|
#define ZF_LOG_TAG "PRODUCTION_TESTING"
|
||
|
#include "zf_log/zf_log.h"
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdbool.h>
|
||
|
#include <stdint.h>
|
||
|
#include <string.h>
|
||
|
#include "io_utils/io_utils_fs.h"
|
||
|
#include "io_utils/io_utils.h"
|
||
|
#include "production_testing.h"
|
||
|
|
||
|
//===================================================================
|
||
|
/*void production_testing_lcd_key_callback(void* context, int key1, int key2)
|
||
|
{
|
||
|
//printf("%d, %d\n", key1, key2);
|
||
|
}*/
|
||
|
|
||
|
//===================================================================
|
||
|
/*void production_testing_powermon_callback(void* context, hat_powermon_state_st* state)
|
||
|
{
|
||
|
}*/
|
||
|
|
||
|
//===================================================================
|
||
|
int production_init(production_sequence_st* prod, production_test_st* tests, int num_tests, void* context)
|
||
|
{
|
||
|
memset(prod, 0, sizeof(production_sequence_st));
|
||
|
|
||
|
// init the power-monitor
|
||
|
if (hat_powermon_init(&prod->powermon, PROD_TESTING_PWR_MON_ADDR, /*production_testing_powermon_callback*/NULL, prod) != 0)
|
||
|
{
|
||
|
ZF_LOGE("Failed to init power monitor");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
hat_powermon_set_power_state(&prod->powermon, false);
|
||
|
|
||
|
if (lcd_init(&prod->lcd, /*production_testing_lcd_key_callback*/NULL, prod) != 0)
|
||
|
{
|
||
|
ZF_LOGE("LCD init failed");
|
||
|
return -1;
|
||
|
}
|
||
|
//lcd_set_params(&prod->lcd, 255, 190)
|
||
|
|
||
|
io_utils_get_rpi_info(&prod->tester.rpi_info);
|
||
|
|
||
|
prod->context = context;
|
||
|
prod->tests = tests;
|
||
|
prod->number_of_tests = num_tests;
|
||
|
prod->current_test_number = 0;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//===================================================================
|
||
|
int production_set_git_repo(production_sequence_st* prod, char* pat, char* repo, char* dir)
|
||
|
{
|
||
|
strcpy(prod->git_pat_path, pat);
|
||
|
strcpy(prod->git_repo, repo);
|
||
|
strcpy(prod->git_res_directory, dir);
|
||
|
|
||
|
lcd_writeln(&prod->lcd, "CaribouLite Tst", "Git repo setup", true);
|
||
|
|
||
|
// read the PAT file
|
||
|
FILE* fid = NULL;
|
||
|
fid = fopen(prod->git_pat_path, "r");
|
||
|
if (fid == NULL)
|
||
|
{
|
||
|
ZF_LOGE("opening file '%s' for reading failed", prod->git_pat_path);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
char* st = fgets(prod->git_pat_user, 255, fid);
|
||
|
if (st == NULL)
|
||
|
{
|
||
|
ZF_LOGE("PAT file doesn't contain username");
|
||
|
return -1;
|
||
|
}
|
||
|
int len = strlen(prod->git_pat_user);
|
||
|
if (prod->git_pat_user[len-1] == '\n' || prod->git_pat_user[len-1] == '\r')
|
||
|
{
|
||
|
prod->git_pat_user[len-1] = 0;
|
||
|
}
|
||
|
|
||
|
st = fgets(prod->git_pat_pass, 255, fid);
|
||
|
if (st == NULL)
|
||
|
{
|
||
|
ZF_LOGE("PAT file doesn't contain pass");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
len = strlen(prod->git_pat_pass);
|
||
|
if (prod->git_pat_pass[len-1] == '\n' || prod->git_pat_pass[len-1] == '\r')
|
||
|
{
|
||
|
prod->git_pat_pass[len-1] = 0;
|
||
|
}
|
||
|
|
||
|
fclose(fid);
|
||
|
|
||
|
// create commands
|
||
|
sprintf(prod->git_base_command, "git --git-dir=%s/.git/ --work-tree=%s",
|
||
|
prod->git_res_directory,
|
||
|
prod->git_res_directory);
|
||
|
|
||
|
sprintf(prod->git_add_command, "%s add --all", prod->git_base_command);
|
||
|
sprintf(prod->git_commit_command, "%s commit -m", prod->git_base_command);
|
||
|
|
||
|
// git push https://user:pass@yourrepo.com/path HEAD
|
||
|
sprintf(prod->git_push_command, "%s push https://%s:%s@%s", prod->git_base_command,
|
||
|
prod->git_pat_user,
|
||
|
prod->git_pat_pass,
|
||
|
prod->git_repo);
|
||
|
|
||
|
sprintf(prod->git_pull_command, "%s pull https://%s:%s@%s", prod->git_base_command,
|
||
|
prod->git_pat_user,
|
||
|
prod->git_pat_pass,
|
||
|
prod->git_repo);
|
||
|
|
||
|
|
||
|
ZF_LOGI("GIT REPO PARAMETERS");
|
||
|
ZF_LOGI("BASE COMMAND: %s", prod->git_base_command);
|
||
|
ZF_LOGI("ADD COMMAND: %s", prod->git_add_command);
|
||
|
ZF_LOGI("COMMIT COMMAND: %s", prod->git_commit_command);
|
||
|
//ZF_LOGI("PUSH COMMAND: %s", prod->git_push_command);
|
||
|
//ZF_LOGI("PULL COMMAND: %s", prod->git_pull_command);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//===================================================================
|
||
|
void production_git_sync_sequence(production_sequence_st* prod, char* commit_string)
|
||
|
{
|
||
|
char pull_command[1500] = {0};
|
||
|
char add_command[1500] = {0};
|
||
|
char commit_command[1700] = {0};
|
||
|
char push_command[1500] = {0};
|
||
|
char *argv_pull[64] = {0};
|
||
|
char *argv_add[64] = {0};
|
||
|
char *argv_commit[64] = {0};
|
||
|
char *argv_push[64] = {0};
|
||
|
|
||
|
char commit_str[256] = {0};
|
||
|
|
||
|
lcd_writeln(&prod->lcd, "CaribouLite Tst", "Git repo sync", true);
|
||
|
|
||
|
for (unsigned int i = 0; i<strlen(commit_string); i++)
|
||
|
{
|
||
|
if (commit_string[i] == ' ') commit_str[i] = '_';
|
||
|
else commit_str[i] = commit_string[i];
|
||
|
}
|
||
|
|
||
|
sprintf(pull_command, "%s", prod->git_pull_command);
|
||
|
sprintf(add_command, "%s", prod->git_add_command);
|
||
|
sprintf(commit_command, "%s '%s'", prod->git_commit_command, commit_str);
|
||
|
sprintf(push_command, "%s", prod->git_push_command);
|
||
|
|
||
|
lcd_writeln(&prod->lcd, "CaribouLite Tst", "Git repo pull", true);
|
||
|
ZF_LOGI("GIT PULL");
|
||
|
io_utils_parse_command(pull_command, argv_pull);
|
||
|
io_utils_execute_command(argv_pull);
|
||
|
|
||
|
ZF_LOGI("GIT ADD");
|
||
|
io_utils_parse_command(add_command, argv_add);
|
||
|
io_utils_execute_command(argv_add);
|
||
|
|
||
|
lcd_writeln(&prod->lcd, "CaribouLite Tst", "Git repo commit", true);
|
||
|
ZF_LOGI("GIT COMMIT");
|
||
|
io_utils_parse_command(commit_command, argv_commit);
|
||
|
io_utils_execute_command(argv_commit);
|
||
|
|
||
|
lcd_writeln(&prod->lcd, "CaribouLite Tst", "Git repo push", true);
|
||
|
ZF_LOGI("GIT PUSH");
|
||
|
io_utils_parse_command(push_command, argv_push);
|
||
|
io_utils_execute_command(argv_push);
|
||
|
}
|
||
|
|
||
|
//===================================================================
|
||
|
int production_close(production_sequence_st* prod)
|
||
|
{
|
||
|
ZF_LOGI("CLOSING LCD");
|
||
|
lcd_writeln(&prod->lcd, "CL TESTER", "GOODBYE!", true);
|
||
|
lcd_close(&prod->lcd);
|
||
|
|
||
|
ZF_LOGI("CLOSING HAT MON");
|
||
|
hat_powermon_set_power_state(&prod->powermon, false);
|
||
|
hat_powermon_release(&prod->powermon);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//===================================================================
|
||
|
int production_rewind(production_sequence_st* prod)
|
||
|
{
|
||
|
prod->current_test_number = 0;
|
||
|
prod->current_tests_pass = true;
|
||
|
prod->operator_set_version = production_sys_version_ism;
|
||
|
prod->serial_number_written_and_valid = false;
|
||
|
prod->serial_number = 0;
|
||
|
prod->system_type_valid = false;
|
||
|
memset(prod->product_name, 0, sizeof(prod->product_name));
|
||
|
hat_powermon_set_power_state(&prod->powermon, false);
|
||
|
|
||
|
lcd_writeln(&prod->lcd, "TESTER", "RESTARTS...", true);
|
||
|
|
||
|
for ( prod->current_test_number = 0;
|
||
|
prod->current_test_number < prod->number_of_tests;
|
||
|
prod->current_test_number ++ )
|
||
|
{
|
||
|
production_test_st* current_test = &prod->tests[prod->current_test_number];
|
||
|
current_test->started = false;
|
||
|
current_test->finished = false;
|
||
|
|
||
|
memset (¤t_test->start_time_of_test, 0, sizeof(struct tm));
|
||
|
memset (¤t_test->end_time_of_test, 0, sizeof(struct tm));
|
||
|
|
||
|
current_test->test_result_float = 0.0;
|
||
|
memset(current_test->test_result_textual, 0, sizeof(current_test->test_result_textual));
|
||
|
current_test->test_pass = false;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
#define PROD_GET_TIME(T) {time_t time_now; time(&time_now); memcpy(&(T),gmtime(&time_now),sizeof(struct tm));}
|
||
|
|
||
|
//===================================================================
|
||
|
int production_start_tests(production_sequence_st* prod)
|
||
|
{
|
||
|
char line1[128], line2[128];
|
||
|
prod->current_tests_pass = true;
|
||
|
|
||
|
for ( prod->current_test_number = 0;
|
||
|
prod->current_test_number < prod->number_of_tests;
|
||
|
prod->current_test_number ++ )
|
||
|
{
|
||
|
production_test_st* current_test = &prod->tests[prod->current_test_number];
|
||
|
ZF_LOGI("Starting test No. %d ['%s']", prod->current_test_number, current_test->test_name);
|
||
|
|
||
|
sprintf(line1, "Testing [%d]", prod->current_test_number);
|
||
|
sprintf(line2, "%s", current_test->name_short);
|
||
|
lcd_writeln(&prod->lcd, line1, line2, true);
|
||
|
|
||
|
current_test->test_number = prod->current_test_number;
|
||
|
|
||
|
PROD_GET_TIME(current_test->start_time_of_test);
|
||
|
current_test->started = true;
|
||
|
|
||
|
if (current_test->func != NULL)
|
||
|
{
|
||
|
current_test->test_pass = current_test->func(prod->context, prod, prod->current_test_number);
|
||
|
|
||
|
sprintf(line2, "%d %s", prod->current_test_number, current_test->name_short);
|
||
|
lcd_writeln(&prod->lcd, line2, current_test->test_pass?"Pass":"Fail", true);
|
||
|
|
||
|
if (!current_test->test_pass)
|
||
|
{
|
||
|
ZF_LOGD("Test '%s' Failed: '%s'", current_test->test_name, current_test->test_result_textual);
|
||
|
prod->current_tests_pass = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
current_test->finished = true;
|
||
|
PROD_GET_TIME(current_test->end_time_of_test);
|
||
|
ZF_LOGI("Finished test No. %d ['%s'] => %s", prod->current_test_number, current_test->test_name,
|
||
|
current_test->test_pass ? "PASS" : "FAIL");
|
||
|
|
||
|
if (!prod->current_tests_pass) break;
|
||
|
}
|
||
|
|
||
|
hat_powermon_set_power_state(&prod->powermon, false);
|
||
|
|
||
|
return prod->current_tests_pass;
|
||
|
}
|
||
|
|
||
|
//===================================================================
|
||
|
int production_generate_event_file(char* path, char* event, char* tester)
|
||
|
{
|
||
|
char filename[256] = {0};
|
||
|
char date1[128] = {0};
|
||
|
|
||
|
struct tm event_time;
|
||
|
PROD_GET_TIME(event_time);
|
||
|
|
||
|
strftime(date1, 128, "%Y_%m_%d__%H_%M_%S", &event_time);
|
||
|
sprintf(filename, "%s/events/%s__%s.yml", path, date1, tester);
|
||
|
|
||
|
FILE* fid = fopen(filename, "w");
|
||
|
if (fid == NULL)
|
||
|
{
|
||
|
ZF_LOGE("File opening failed for results generation");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
fprintf(fid, "%s", event);
|
||
|
|
||
|
fflush(fid);
|
||
|
fclose(fid);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//===================================================================
|
||
|
int production_generate_report(production_sequence_st* prod, char* path, uint32_t serial_number)
|
||
|
{
|
||
|
uint32_t i;
|
||
|
|
||
|
char filename[256] = {0};
|
||
|
char date1[128] = {0};
|
||
|
char date[256] = {0};
|
||
|
|
||
|
lcd_writeln(&prod->lcd, "Generating", "Report", true);
|
||
|
strftime(date1, 128, "%Y_%m_%d__%H_%M_%S", &prod->tests[0].start_time_of_test);
|
||
|
strftime(date, 256, "%d/%m/%Y %H:%M:%S", &prod->tests[0].start_time_of_test);
|
||
|
sprintf(filename, "%s/boards/%s__%08x.yml", path, date1, serial_number);
|
||
|
|
||
|
FILE* fid = fopen(filename, "w");
|
||
|
if (fid == NULL)
|
||
|
{
|
||
|
ZF_LOGE("File opening failed for results generation");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
fprintf(fid, "version: 1\n");
|
||
|
fprintf(fid, "file_type: cariboulite_test_results\n");
|
||
|
fprintf(fid, "date: %s\n", date);
|
||
|
fprintf(fid, "product_name: %s\n", prod->product_name);
|
||
|
fprintf(fid, "rpi_serial_number: %s\n", prod->tester.rpi_info.serial_number);
|
||
|
fprintf(fid, "summary_test_results: %s\n", prod->current_tests_pass?"PASS":"FAIL");
|
||
|
fprintf(fid, "test_results:\n");
|
||
|
|
||
|
for (i = 0; i < prod->number_of_tests; i++)
|
||
|
{
|
||
|
fprintf(fid, "\t%s: \"%s\"\n", prod->tests[i].test_name, prod->tests[i].test_result_textual);
|
||
|
fflush(fid);
|
||
|
}
|
||
|
|
||
|
fclose(fid);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//===================================================================
|
||
|
int production_wait_for_button(production_sequence_st* prod, lcd_button_en but, char* top_line, char* bottom_line)
|
||
|
{
|
||
|
int key1, key2;
|
||
|
lcd_writeln(&prod->lcd, top_line, bottom_line, true);
|
||
|
|
||
|
while (1)
|
||
|
{
|
||
|
io_utils_usleep(100000);
|
||
|
lcd_get_keys(&prod->lcd, &key1, &key2);
|
||
|
|
||
|
if (but == lcd_button_bottom && key1)
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
else if (but == lcd_button_top && key2)
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//===================================================================
|
||
|
int production_wait_input(production_sequence_st* prod, lcd_button_en *but, char* top_line, char* bottom_line)
|
||
|
{
|
||
|
int key1, key2;
|
||
|
lcd_writeln(&prod->lcd, top_line, bottom_line, true);
|
||
|
|
||
|
while (1)
|
||
|
{
|
||
|
io_utils_usleep(100000);
|
||
|
lcd_get_keys(&prod->lcd, &key1, &key2);
|
||
|
|
||
|
if (key1)
|
||
|
{
|
||
|
if (but) *but = lcd_button_bottom;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
if (key2)
|
||
|
{
|
||
|
if (but) *but = lcd_button_top;
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
//===================================================================
|
||
|
int production_monitor_power_fault(production_sequence_st* prod, bool* fault, float *i, float* v, float* p)
|
||
|
{
|
||
|
char line2[32];
|
||
|
if (hat_powermon_read_fault(&prod->powermon, fault) != 0)
|
||
|
{
|
||
|
//ZF_LOGI("HAT Power-Monitor reader thread finished");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (hat_powermon_read_data(&prod->powermon, i, v, p) != 0)
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
sprintf(line2, "%s %.1f mA", (*fault)?"FLT":"Okay", *i);
|
||
|
lcd_writeln(&prod->lcd, "Power on...", line2, true);
|
||
|
return 0;
|
||
|
}
|