init
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
#define DEBUG_FLAG true
|
||||
|
||||
#include "programm.h"
|
||||
ProgClass* p;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
p = new ProgClass(&Serial);
|
||||
#if defined(DEBUG_FLAG) && DEBUG_FLAG
|
||||
Serial.println("Init loading!");
|
||||
#endif
|
||||
p->loadFromDisplay();
|
||||
#if defined(DEBUG_FLAG) && DEBUG_FLAG
|
||||
Serial.println("Init finished!");
|
||||
#endif
|
||||
}
|
||||
|
||||
void loop() {
|
||||
p->loop();
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{C5F80730-F44F-4478-BDAE-6634EFC2CA88}</ProjectGuid>
|
||||
<RootNamespace>Zeit_V2</RootNamespace>
|
||||
<ProjectName>Zeit-V2</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>
|
||||
</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>
|
||||
</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<IncludePath>C:\Users\schell\Documents\Arduino\libraries\Ethernet2\src;D:\Programme\Arduino\hardware\arduino\avr\libraries\SoftwareSerial;C:\Users\schell\Documents\Arduino\libraries\Time;D:\Programme\Arduino\hardware\arduino\avr\libraries\SPI;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>D:\Programme\Arduino\libraries;C:\Users\schell\AppData\Local\arduino15\packages\arduino\hardware\avr\1.6.11\libraries;D:\Programme\Visual Studio\Common7\IDE\Extensions\hunc4op4.xpd\Micro Platforms\default\debuggers;C:\Users\schell\Documents\Arduino\libraries;C:\Users\schell\AppData\Local\arduino15\packages\arduino\hardware\avr\1.6.11\cores\arduino;C:\Users\schell\AppData\Local\arduino15\packages\arduino\hardware\avr\1.6.11\variants\standard;C:\Users\schell\Documents\Arduino\Zeit-V2\Zeit-V2;D:\Programme\Arduino\hardware\tools\avr/avr/include/;D:\Programme\Arduino\hardware\tools\avr//avr/include/avr/;D:\Programme\Arduino\hardware\tools\avr/lib\gcc\avr\4.8.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<ForcedIncludeFiles>C:\Users\schell\Documents\Arduino\Zeit-V2\Zeit-V2\__vm\.Zeit-V2.vsarduino.h;%(ForcedIncludeFiles)</ForcedIncludeFiles>
|
||||
<IgnoreStandardIncludePath>false</IgnoreStandardIncludePath>
|
||||
<PreprocessorDefinitions>__AVR_ATmega328p__;__AVR_ATmega328P__;F_CPU=16000000L;ARDUINO=10607;ARDUINO_AVR_UNO;ARDUINO_ARCH_AVR;__cplusplus=201103L;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Zeit-V2.ino">
|
||||
<FileType>CppCode</FileType>
|
||||
<DeploymentContent>true</DeploymentContent>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="button.h" />
|
||||
<ClInclude Include="display.h" />
|
||||
<ClInclude Include="network.h" />
|
||||
<ClInclude Include="programm.h" />
|
||||
<ClInclude Include="rfid.h" />
|
||||
<ClInclude Include="__vm\.Zeit-V2.vsarduino.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Zeit-V2.ino" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="button.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="display.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="network.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="programm.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rfid.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="__vm\.Zeit-V2.vsarduino.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,27 @@
|
||||
class ButtonClass {
|
||||
private:
|
||||
void init(void);
|
||||
public:
|
||||
ButtonClass(void);
|
||||
bool check(uint8_t job);
|
||||
uint8_t read(void);
|
||||
};
|
||||
|
||||
|
||||
ButtonClass::ButtonClass(void) {
|
||||
this->init();
|
||||
}
|
||||
|
||||
void ButtonClass::init(void) {
|
||||
pinMode(2, INPUT_PULLUP);
|
||||
pinMode(3, INPUT_PULLUP);
|
||||
}
|
||||
|
||||
bool ButtonClass::check(uint8_t job) {
|
||||
return ((digitalRead(2) == LOW && job != 1) || (digitalRead(3) == LOW && job != 2));
|
||||
}
|
||||
|
||||
uint8_t ButtonClass::read(void){
|
||||
return digitalRead(2)==LOW?1:2;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
#if !defined(DEBUG_FLAG)
|
||||
#define DEBUG_FLAG false
|
||||
#endif
|
||||
|
||||
#include <SoftwareSerial.h>
|
||||
#if DEBUG_FLAG
|
||||
#include <HardwareSerial.h>
|
||||
#endif
|
||||
|
||||
class DispClass {
|
||||
private:
|
||||
SoftwareSerial* serD;
|
||||
#if DEBUG_FLAG
|
||||
HardwareSerial* _debug;
|
||||
#endif
|
||||
void init(void);
|
||||
public:
|
||||
#if DEBUG_FLAG
|
||||
DispClass(HardwareSerial *debug);
|
||||
#else
|
||||
DispClass(void);
|
||||
#endif
|
||||
void print(String text);
|
||||
void setTimeout(unsigned long timeout);
|
||||
String readStringUntil(char terminator);
|
||||
};
|
||||
|
||||
#if DEBUG_FLAG
|
||||
DispClass::DispClass(HardwareSerial *debug) {
|
||||
this->_debug = debug;
|
||||
this->init();
|
||||
}
|
||||
#else
|
||||
DispClass::DispClass(void) {
|
||||
this->init();
|
||||
}
|
||||
#endif
|
||||
|
||||
void DispClass::init(void) {
|
||||
this->serD = new SoftwareSerial(7, 6);
|
||||
this->serD->begin(9600);
|
||||
}
|
||||
|
||||
void DispClass::print(String text) {
|
||||
#if DEBUG_FLAG
|
||||
this->_debug->println("d->: "+text);
|
||||
#endif
|
||||
this->serD->listen();
|
||||
this->serD->println(text);
|
||||
}
|
||||
|
||||
void DispClass::setTimeout(unsigned long timeout) {
|
||||
this->serD->setTimeout(timeout);
|
||||
}
|
||||
|
||||
String DispClass::readStringUntil(char terminator) {
|
||||
return this->serD->readStringUntil(terminator);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
#if !defined(DEBUG_FLAG)
|
||||
#define DEBUG_FLAG false
|
||||
#endif
|
||||
|
||||
#include <SPI.h>
|
||||
#include <Ethernet2.h>
|
||||
#if DEBUG_FLAG
|
||||
#include <HardwareSerial.h>
|
||||
#endif
|
||||
|
||||
class NetClass {
|
||||
private:
|
||||
#if DEBUG_FLAG
|
||||
HardwareSerial* _debug;
|
||||
#endif
|
||||
EthernetClass* e;
|
||||
void init(void);
|
||||
// Mac-Adress of the Ethernet-Shield
|
||||
uint8_t mac[6] = { 0x90, 0xA2, 0xDA, 0x10, 0x4F, 0xA4 };
|
||||
public:
|
||||
#if DEBUG_FLAG
|
||||
NetClass(HardwareSerial *debug);
|
||||
#else
|
||||
NetClass(void);
|
||||
#endif
|
||||
};
|
||||
|
||||
#if DEBUG_FLAG
|
||||
NetClass::NetClass(HardwareSerial *debug) {
|
||||
this->_debug = debug;
|
||||
this->init();
|
||||
}
|
||||
#else
|
||||
NetClass::NetClass(void) {
|
||||
this->init();
|
||||
}
|
||||
#endif
|
||||
|
||||
void NetClass::init(void) {
|
||||
pinMode(10, OUTPUT);
|
||||
digitalWrite(10, HIGH);
|
||||
#if DEBUG_FLAG
|
||||
this->_debug->println("Start Network!");
|
||||
this->_debug->println("DHCP Request");
|
||||
#endif
|
||||
this->e = &Ethernet;
|
||||
if (this->e->begin(mac) == 0) {
|
||||
#if DEBUG_FLAG
|
||||
this->_debug->println("DHCP Failed, Use Link-Local Adress");
|
||||
#endif
|
||||
this->e->begin(mac, IPAddress(169, 254, 1, 177), IPAddress(169, 254, 0, 1), IPAddress(255, 255, 0, 0));
|
||||
}
|
||||
#if DEBUG_FLAG
|
||||
this->_debug->print("Ethernet Started! IP: ");
|
||||
IPAddress ip = Ethernet.localIP();
|
||||
for (byte thisByte = 0; thisByte < 4; thisByte++) {
|
||||
// print the value of each byte of the IP address:
|
||||
this->_debug->print(ip[thisByte], DEC);
|
||||
this->_debug->print(".");
|
||||
}
|
||||
this->_debug->println();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
#if !defined(DEBUG_FLAG)
|
||||
#define DEBUG_FLAG false
|
||||
#endif
|
||||
|
||||
#include <HardwareSerial.h>
|
||||
#include <Time.h>
|
||||
#include <stdlib.h>
|
||||
#include "display.h"
|
||||
#include "network.h"
|
||||
#include "rfid.h"
|
||||
#include "button.h"
|
||||
|
||||
class ProgClass {
|
||||
private:
|
||||
static const int MAX_STORE_DATA = 8;
|
||||
|
||||
HardwareSerial* _usb;
|
||||
DispClass* disp;
|
||||
NetClass* net;
|
||||
RfidClass* rfid;
|
||||
ButtonClass* bu;
|
||||
|
||||
int8_t _storeCount = -1;
|
||||
int8_t _job = -1;
|
||||
int8_t _online = -1;
|
||||
bool _keep = false;
|
||||
String _storeData[MAX_STORE_DATA];
|
||||
String _cmsg;
|
||||
|
||||
void init(void);
|
||||
void parse(String text);
|
||||
bool keepAlive(void);
|
||||
void doJob(String task, String value);
|
||||
|
||||
public:
|
||||
ProgClass(HardwareSerial *usb);
|
||||
void loop(void);
|
||||
void loadFromDisplay(void);
|
||||
};
|
||||
|
||||
ProgClass::ProgClass(HardwareSerial *usb) {
|
||||
this->_usb = usb;
|
||||
this->init();
|
||||
}
|
||||
|
||||
void ProgClass::init(void) {
|
||||
#if DEBUG_FLAG
|
||||
this->_usb->println("Init....");
|
||||
this->disp = new DispClass(this->_usb);
|
||||
this->net = new NetClass(this->_usb);
|
||||
#else
|
||||
this->disp = new DispClass();
|
||||
this->net = new NetClass();
|
||||
#endif
|
||||
this->rfid = new RfidClass();
|
||||
this->bu = new ButtonClass();
|
||||
this->_usb->println("t="+String(now()));
|
||||
}
|
||||
|
||||
void ProgClass::loop(void) {
|
||||
char c;
|
||||
if (this->rfid->hasData()) {
|
||||
if (this->rfid->allowed()) {
|
||||
this->_online = this->_online == 1 ? 0 : 1;
|
||||
this->doJob("tag", this->rfid->getData());
|
||||
this->doJob("online", String(this->_online));
|
||||
delay(1000);
|
||||
}
|
||||
this->rfid->clear();
|
||||
}
|
||||
if (this->_usb->available()) {
|
||||
c = this->_usb->read();
|
||||
if (c == '\n') {
|
||||
this->parse(this->_cmsg);
|
||||
this->_cmsg = "";
|
||||
}
|
||||
else {
|
||||
this->_cmsg += c;
|
||||
}
|
||||
}
|
||||
if (this->bu->check(this->_job)) {
|
||||
this->_job = this->bu->read();
|
||||
this->doJob("job", String(this->_job));
|
||||
this->rfid->clear();
|
||||
}
|
||||
}
|
||||
|
||||
void ProgClass::loadFromDisplay(void) {
|
||||
this->disp->setTimeout(1000);
|
||||
this->disp->print("getJob=1");
|
||||
this->parse(this->disp->readStringUntil('\n'));
|
||||
this->disp->print("getOnline=1");
|
||||
this->parse(this->disp->readStringUntil('\n'));
|
||||
if (this->keepAlive()) {
|
||||
this->disp->print("getStoreCount=1");
|
||||
this->parse(this->disp->readStringUntil('\n'));
|
||||
if (this->_storeCount > 0) {
|
||||
this->disp->print("getStoreData=1");
|
||||
this->parse(this->disp->readStringUntil('\n'));
|
||||
}
|
||||
}
|
||||
if (this->keepAlive()) {
|
||||
this->doJob("getStore", "1");
|
||||
}
|
||||
}
|
||||
|
||||
void ProgClass::parse(String text) {
|
||||
#if DEBUG_FLAG
|
||||
this->_usb->println("i<-: " + text);
|
||||
#endif
|
||||
text.trim();
|
||||
String task = "";
|
||||
String value = "";
|
||||
if (text.indexOf("=") != -1) {
|
||||
task = text.substring(0, text.indexOf("="));
|
||||
value = text.substring(text.indexOf("=") + 1);
|
||||
this->doJob(task, value);
|
||||
}
|
||||
}
|
||||
|
||||
bool ProgClass::keepAlive(void) {
|
||||
this->_usb->setTimeout(1000);
|
||||
this->_keep = false;
|
||||
this->_usb->println("requestKeep=1");
|
||||
String a = this->_usb->readStringUntil('\n');
|
||||
if (a != "") {
|
||||
this->parse(a);
|
||||
}
|
||||
return this->_keep;
|
||||
}
|
||||
|
||||
void ProgClass::doJob(String task, String value) {
|
||||
if (task == "tag") {
|
||||
char hex[15];
|
||||
value.toCharArray(hex, 14);
|
||||
String answ = "tag=" + String(strtol(hex, NULL, 16));
|
||||
answ += ";time=" + String(now());
|
||||
answ += ";job=" + String(this->_job);
|
||||
answ += ";online=" + String(this->_online);
|
||||
if (this->keepAlive()) {
|
||||
this->_usb->println(answ);
|
||||
}
|
||||
else {
|
||||
this->disp->print(answ);
|
||||
}
|
||||
}
|
||||
else if (task == "job") {
|
||||
this->disp->print("job=" + value);
|
||||
}
|
||||
else if (task == "online") {
|
||||
this->disp->print("online=" + value);
|
||||
}
|
||||
else if (task == "time") {
|
||||
setTime(value.toInt());
|
||||
this->_usb->println("t=" + String(now()));
|
||||
}
|
||||
else if (task == "setJob") {
|
||||
this->_job = value.toInt();
|
||||
}
|
||||
else if (task == "setOnline") {
|
||||
this->_online = value.toInt();
|
||||
}
|
||||
else if (task == "keep") {
|
||||
this->_keep = true;
|
||||
}
|
||||
else if (task == "hasCount") {
|
||||
this->_storeCount = value.toInt();
|
||||
}
|
||||
else if (task == "dataStore") {
|
||||
int i = 0;
|
||||
while (true) {
|
||||
if (i == MAX_STORE_DATA) {
|
||||
break;
|
||||
}
|
||||
if (value.indexOf('|') == -1) {
|
||||
this->_storeData[i] = value;
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
this->_storeData[i] = value.substring(0, value.indexOf('|'));
|
||||
value = value.substring(value.indexOf('|') + 1);
|
||||
i++;
|
||||
}
|
||||
this->_storeCount = i;
|
||||
}
|
||||
else if (task == "getStore") {
|
||||
if (this->_storeCount > 0) {
|
||||
for (int i = 0; i < this->_storeCount; i++) {
|
||||
this->_usb->println(this->_storeData[i]);
|
||||
}
|
||||
this->_storeCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#include <SoftwareSerial.h>
|
||||
|
||||
class RfidClass {
|
||||
private:
|
||||
SoftwareSerial* serD;
|
||||
void init(void);
|
||||
String rmsg;
|
||||
public:
|
||||
RfidClass(void);
|
||||
bool hasData(void);
|
||||
String getData(void);
|
||||
bool allowed(void);
|
||||
void clear(void);
|
||||
};
|
||||
|
||||
RfidClass::RfidClass(void) {
|
||||
this->init();
|
||||
}
|
||||
|
||||
void RfidClass::init(void) {
|
||||
this->serD = new SoftwareSerial (9, 8);
|
||||
this->serD->begin(9600);
|
||||
}
|
||||
|
||||
bool RfidClass::hasData(void) {
|
||||
this->serD->listen();
|
||||
if(this->serD->available()) {
|
||||
this->rmsg += (char)this->serD->read();
|
||||
}
|
||||
if(this->rmsg.length() >= 14) {
|
||||
this->rmsg = this->rmsg.substring(1,13);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
String RfidClass::getData(void){
|
||||
return this->rmsg;
|
||||
}
|
||||
|
||||
bool RfidClass::allowed() {
|
||||
return (this->rmsg == "0A006AB7AE79");
|
||||
}
|
||||
|
||||
void RfidClass::clear(void) {
|
||||
this->rmsg = "";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user