Add C3 FCC regulatory info page (#21833)

* move uninstall to software

* fcc page

* only tici

* cleanup

* more cleanup
pull/21834/head
Adeeb Shihadeh 2021-08-02 20:02:07 -07:00 committed by GitHub
parent 429c4d2640
commit a96f358966
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 150 additions and 56 deletions

View File

@ -0,0 +1,54 @@
<!DOCTYPE html>
<body>
<h3>Unique Identifier</h3>
<p>comma three</p>
<h3>Authorized Components</h3>
<h5>Thundersoft TurboX D845 SOM</h5>
<p>FCC ID: 2AOHHTURBOXSOMD845</p>
<h5>Quectel/EG25-G</h5>
<p>FCC ID: XMR201903EG25GM</p>
<p>
This device complies with Part 15 of the FCC Rules.
Operation is subject to the following two conditions:
<p>(1) this device may not cause harmful interference, and
<p>(2) this device must accept any interference received, including interference that may cause undesired operation.</p>
The following test reports are subject to this declaration:
Test report number: HR20191001605
Issue date: 2019-2-21
The following manufacturer/importer/entity (located in the USA) is responsible for this declaration:
Company name: Quectel Wireless Solutions Co., Ltd.
Name/Title (legal representative): Yin JiXiong
Address: 7th Floor, Hongye Building, No.1801 Hongmei Road, Xuhui District, Shanghai 200233, China
Phone: +8602150086326 Extension: 800
Fax: +862153253668
E-mail: johnny.xiang@quectel.com
</p>
<h3>Responsible Party - U.S. Contact Information</h3>
<p>comma.ai</p>
<p>501 W Broadway St</p>
<p>STE A #403</p>
<p>San Diego, California</p>
<p>92101</p>
<p>United States</p>
<p>support@comma.ai</p>
<h3>Responsible Party - U.S. Contact Information</h3>
<p> This device complies with part 15 of the FCC Rules. Operation is subject to the following two conditions: (1) This device may not cause harmful interference, and (2) this device must accept any interference received, including interference that may cause undesired operation. Note: This equipment has been tested and found to comply with the limits for a Class B digital device, pursuant to part 15 of the FCC Rules. These limits are designed to provide reasonable protection against harmful interference in a residential installation.</p>
<p>This equipment generates, uses, and can radiate radio frequency energy and, if not installed and used in accordance with the instructions, may cause harmful interference to radio communications. However, there is no guarantee that interference will not occur in a particular installation.</p>
<p>If this equipment does cause harmful interference to radio or television reception, which can be determined by turning the equipment off and on, the user is encouraged to try to correct the interference by one or more of the following measures:</p>
<p>Reorient or relocate the receiving antenna.</p>
<p>Increase the separation between the equipment and receiver.</p>
<p>Connect the equipment to an outlet on a circuit different from that to which the receiver is connected.</p>
<p>Consult the dealer or an experienced radio/TV technician for help.</p>
<p>Changes or modifications to this product not expressly approved by the party responsible for compliance could void the electromagnetic compatibility (EMC) and wireless compliance and negate your authority to operate the product.</p>
<p>This product has demonstrated EMC compliance under conditions that included the use of compliant peripheral devices and shielded cables between system components. It is important that you use compliant peripheral devices and shielded cables between system components to reduce the possibility of causing interference to radios, televisions, and other electronic devices.</p>
<p>The radiated output power of this device meets the limits of FCC/IC radio frequency exposure limits. This device should be operated with a minimum separation distance of 20 cm (8 inches) between the equipment and a person's body.</p>
</body>
</html>

View File

@ -23,6 +23,7 @@
#include "selfdrive/ui/qt/widgets/toggle.h"
#include "selfdrive/ui/ui.h"
#include "selfdrive/ui/qt/util.h"
#include "selfdrive/ui/qt/qt_window.h"
TogglesPanel::TogglesPanel(QWidget *parent) : QWidget(parent) {
QVBoxLayout *main_layout = new QVBoxLayout(this);
@ -147,14 +148,16 @@ DevicePanel::DevicePanel(QWidget* parent) : QWidget(parent) {
});
}
auto uninstallBtn = new ButtonControl("Uninstall " + getBrand(), "UNINSTALL");
connect(uninstallBtn, &ButtonControl::clicked, [=]() {
if (ConfirmationDialog::confirm("Are you sure you want to uninstall?", this)) {
Params().putBool("DoUninstall", true);
}
});
ButtonControl *regulatoryBtn = nullptr;
if (Hardware::TICI() || true) {
regulatoryBtn = new ButtonControl("Regulatory", "VIEW", "");
connect(regulatoryBtn, &ButtonControl::clicked, [=]() {
const std::string txt = util::read_file(ASSET_PATH.toStdString() + "/offroad/fcc.html");
RichTextDialog::alert(QString::fromStdString(txt), this);
});
}
for (auto btn : {dcamBtn, resetCalibBtn, retrainingBtn, uninstallBtn}) {
for (auto btn : {dcamBtn, resetCalibBtn, retrainingBtn, regulatoryBtn}) {
if (btn) {
main_layout->addWidget(horizontal_line());
connect(parent, SIGNAL(offroadTransition(bool)), btn, SLOT(setEnabled(bool)));
@ -219,11 +222,18 @@ SoftwarePanel::SoftwarePanel(QWidget* parent) : QWidget(parent) {
QWidget *widgets[] = {versionLbl, lastUpdateLbl, updateBtn, gitBranchLbl, gitCommitLbl, osVersionLbl};
for (int i = 0; i < std::size(widgets); ++i) {
main_layout->addWidget(widgets[i]);
if (i < std::size(widgets) - 1) {
main_layout->addWidget(horizontal_line());
}
main_layout->addWidget(horizontal_line());
}
auto uninstallBtn = new ButtonControl("Uninstall " + getBrand(), "UNINSTALL");
connect(uninstallBtn, &ButtonControl::clicked, [=]() {
if (ConfirmationDialog::confirm("Are you sure you want to uninstall?", this)) {
Params().putBool("DoUninstall", true);
}
});
connect(parent, SIGNAL(offroadTransition(bool)), uninstallBtn, SLOT(setEnabled(bool)));
main_layout->addWidget(uninstallBtn);
fs_watch = new QFileSystemWatcher(this);
QObject::connect(fs_watch, &QFileSystemWatcher::fileChanged, [=](const QString path) {
int update_failed_count = params.get<int>("UpdateFailedCount").value_or(0);

View File

@ -2,14 +2,39 @@
#include <QPushButton>
#include "selfdrive/hardware/hw.h"
#include "selfdrive/ui/qt/util.h"
#include "selfdrive/ui/qt/qt_window.h"
#include "selfdrive/hardware/hw.h"
#include "selfdrive/ui/qt/widgets/scrollview.h"
QDialogBase::QDialogBase(QWidget *parent) : QDialog(parent) {
Q_ASSERT(parent != nullptr);
parent->installEventFilter(this);
setWindowFlags(Qt::Popup);
setStyleSheet(R"(
* {
outline: none;
color: white;
font-family: Inter;
}
QDialogBase {
background-color: black;
}
QPushButton {
height: 160;
font-size: 55px;
font-weight: 400;
border-radius: 10px;
color: white;
background-color: #333333;
}
QPushButton:pressed {
background-color: #444444;
}
)");
}
bool QDialogBase::eventFilter(QObject *o, QEvent *e) {
@ -19,6 +44,11 @@ bool QDialogBase::eventFilter(QObject *o, QEvent *e) {
return QDialog::eventFilter(o, e);
}
int QDialogBase::exec() {
setMainWindow(this);
return QDialog::exec();
}
InputDialog::InputDialog(const QString &title, QWidget *parent, const QString &subtitle, bool secret) : QDialogBase(parent) {
main_layout = new QVBoxLayout(this);
main_layout->setContentsMargins(50, 55, 50, 50);
@ -112,15 +142,6 @@ InputDialog::InputDialog(const QString &title, QWidget *parent, const QString &s
});
main_layout->addWidget(k, 2, Qt::AlignBottom);
setStyleSheet(R"(
* {
outline: none;
color: white;
font-family: Inter;
background-color: black;
}
)");
}
QString InputDialog::getText(const QString &prompt, QWidget *parent, const QString &subtitle,
@ -136,11 +157,6 @@ QString InputDialog::text() {
return line->text();
}
int InputDialog::exec() {
setMainWindow(this);
return QDialog::exec();
}
void InputDialog::show() {
setMainWindow(this);
}
@ -165,9 +181,12 @@ void InputDialog::setMinLength(int length) {
minLength = length;
}
// ConfirmationDialog
ConfirmationDialog::ConfirmationDialog(const QString &prompt_text, const QString &confirm_text, const QString &cancel_text,
QWidget *parent) : QDialogBase(parent) {
QFrame *container = new QFrame(this);
container->setStyleSheet("QFrame { border-radius: 0; background-color: #ECECEC; }");
QVBoxLayout *main_layout = new QVBoxLayout(container);
main_layout->setContentsMargins(32, 120, 32, 32);
@ -197,28 +216,6 @@ ConfirmationDialog::ConfirmationDialog(const QString &prompt_text, const QString
QVBoxLayout *outer_layout = new QVBoxLayout(this);
outer_layout->setContentsMargins(210, 170, 210, 170);
outer_layout->addWidget(container);
setWindowFlags(Qt::Popup);
setStyleSheet(R"(
ConfirmationDialog {
background-color: black;
}
QFrame {
border-radius: 0;
background-color: #ECECEC;
}
QPushButton {
height: 160;
font-size: 55px;
font-weight: 400;
border-radius: 10px;
color: white;
background-color: #333333;
}
QPushButton:pressed {
background-color: #444444;
}
)");
}
bool ConfirmationDialog::alert(const QString &prompt_text, QWidget *parent) {
@ -231,7 +228,34 @@ bool ConfirmationDialog::confirm(const QString &prompt_text, QWidget *parent) {
return d.exec();
}
int ConfirmationDialog::exec() {
setMainWindow(this);
return QDialog::exec();
// RichTextDialog
RichTextDialog::RichTextDialog(const QString &prompt_text, const QString &btn_text,
QWidget *parent) : QDialogBase(parent) {
QFrame *container = new QFrame(this);
container->setStyleSheet("QFrame { background-color: #1B1B1B; }");
QVBoxLayout *main_layout = new QVBoxLayout(container);
main_layout->setContentsMargins(32, 32, 32, 32);
QLabel *prompt = new QLabel(prompt_text, this);
prompt->setWordWrap(true);
prompt->setAlignment(Qt::AlignLeft);
prompt->setTextFormat(Qt::RichText);
prompt->setStyleSheet("font-size: 42px; font-weight: light; color: #C9C9C9; margin: 45px;");
main_layout->addWidget(new ScrollView(prompt, this), 1, Qt::AlignTop);
// confirm button
QPushButton* confirm_btn = new QPushButton(btn_text);
main_layout->addWidget(confirm_btn);
QObject::connect(confirm_btn, &QPushButton::clicked, this, &QDialog::accept);
QVBoxLayout *outer_layout = new QVBoxLayout(this);
outer_layout->setContentsMargins(100, 100, 100, 100);
outer_layout->addWidget(container);
}
bool RichTextDialog::alert(const QString &prompt_text, QWidget *parent) {
auto d = RichTextDialog(prompt_text, "Ok", parent);
return d.exec();
}

View File

@ -16,6 +16,9 @@ class QDialogBase : public QDialog {
protected:
QDialogBase(QWidget *parent);
bool eventFilter(QObject *o, QEvent *e) override;
public slots:
int exec() override;
};
class InputDialog : public QDialogBase {
@ -39,9 +42,6 @@ private:
QVBoxLayout *main_layout;
QPushButton *eye_btn;
public slots:
int exec() override;
private slots:
void handleEnter();
@ -58,7 +58,13 @@ public:
const QString &cancel_text, QWidget* parent);
static bool alert(const QString &prompt_text, QWidget *parent);
static bool confirm(const QString &prompt_text, QWidget *parent);
public slots:
int exec() override;
};
// larger ConfirmationDialog for rich text
class RichTextDialog : public QDialogBase {
Q_OBJECT
public:
explicit RichTextDialog(const QString &prompt_text, const QString &btn_text, QWidget* parent);
static bool alert(const QString &prompt_text, QWidget *parent);
};