mirror of
https://github.com/fairwaves/UHD-Fairwaves.git
synced 2025-11-03 13:33:15 +00:00
Compare commits
5 Commits
1.0.9
...
idle_reset
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6330a16b16 | ||
|
|
50a1b928ec | ||
|
|
41a94769fe | ||
|
|
b1e80e5c27 | ||
|
|
014e8123a3 |
12
debian/changelog
vendored
12
debian/changelog
vendored
@@ -1,3 +1,15 @@
|
|||||||
|
umtrx (1.0.11) trusty; urgency=low
|
||||||
|
|
||||||
|
* collectd: use 'fairwaves-monitoring' user to run plugin
|
||||||
|
|
||||||
|
-- Kirill Zakharenko <earwin@gmail.com> Sun, 27 Mar 2016 19:37:39 +0100
|
||||||
|
|
||||||
|
umtrx (1.0.10) trusty; urgency=low
|
||||||
|
|
||||||
|
* collectd: rewritten counter collection plugin
|
||||||
|
|
||||||
|
-- Kirill Zakharenko <earwin@gmail.com> Mon, 21 Mar 2016 19:21:00 +0100
|
||||||
|
|
||||||
umtrx (1.0.9) trusty; urgency=low
|
umtrx (1.0.9) trusty; urgency=low
|
||||||
|
|
||||||
* collectd: osmo-nitb counter collection plugin
|
* collectd: osmo-nitb counter collection plugin
|
||||||
|
|||||||
@@ -59,7 +59,11 @@ module ddc_chain
|
|||||||
reg [WIDTH-1:0] rx_fe_i_mux, rx_fe_q_mux;
|
reg [WIDTH-1:0] rx_fe_i_mux, rx_fe_q_mux;
|
||||||
wire realmode;
|
wire realmode;
|
||||||
wire swap_iq;
|
wire swap_iq;
|
||||||
|
|
||||||
|
reg idle_rst;
|
||||||
|
always @(posedge clk)
|
||||||
|
idle_rst <= (rst | ~ddc_enb);
|
||||||
|
|
||||||
setting_reg #(.my_addr(BASE+0)) sr_0
|
setting_reg #(.my_addr(BASE+0)) sr_0
|
||||||
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
|
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
|
||||||
.in(set_data),.out(phase_inc),.changed());
|
.in(set_data),.out(phase_inc),.changed());
|
||||||
@@ -92,9 +96,7 @@ module ddc_chain
|
|||||||
|
|
||||||
// NCO
|
// NCO
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
if(rst)
|
if(idle_rst)
|
||||||
phase <= 0;
|
|
||||||
else if(~ddc_enb)
|
|
||||||
phase <= 0;
|
phase <= 0;
|
||||||
else
|
else
|
||||||
phase <= phase + phase_inc;
|
phase <= phase + phase_inc;
|
||||||
@@ -117,36 +119,36 @@ module ddc_chain
|
|||||||
(.clk(clk), .in(q_cordic), .strobe_in(1'b1), .out(q_cordic_clip));
|
(.clk(clk), .in(q_cordic), .strobe_in(1'b1), .out(q_cordic_clip));
|
||||||
|
|
||||||
// CIC decimator 24 bit I/O
|
// CIC decimator 24 bit I/O
|
||||||
cic_strober cic_strober(.clock(clk),.reset(rst),.enable(ddc_enb),.rate(cic_decim_rate),
|
cic_strober cic_strober(.clock(clk),.reset(idle_rst),.enable(ddc_enb),.rate(cic_decim_rate),
|
||||||
.strobe_fast(1),.strobe_slow(strobe_cic) );
|
.strobe_fast(1),.strobe_slow(strobe_cic) );
|
||||||
|
|
||||||
cic_decim #(.bw(WIDTH))
|
cic_decim #(.bw(WIDTH))
|
||||||
decim_i (.clock(clk),.reset(rst),.enable(ddc_enb),
|
decim_i (.clock(clk),.reset(idle_rst),.enable(ddc_enb),
|
||||||
.rate(cic_decim_rate),.strobe_in(1'b1),.strobe_out(strobe_cic),
|
.rate(cic_decim_rate),.strobe_in(1'b1),.strobe_out(strobe_cic),
|
||||||
.signal_in(i_cordic_clip),.signal_out(i_cic));
|
.signal_in(i_cordic_clip),.signal_out(i_cic));
|
||||||
|
|
||||||
cic_decim #(.bw(WIDTH))
|
cic_decim #(.bw(WIDTH))
|
||||||
decim_q (.clock(clk),.reset(rst),.enable(ddc_enb),
|
decim_q (.clock(clk),.reset(idle_rst),.enable(ddc_enb),
|
||||||
.rate(cic_decim_rate),.strobe_in(1'b1),.strobe_out(strobe_cic),
|
.rate(cic_decim_rate),.strobe_in(1'b1),.strobe_out(strobe_cic),
|
||||||
.signal_in(q_cordic_clip),.signal_out(q_cic));
|
.signal_in(q_cordic_clip),.signal_out(q_cic));
|
||||||
|
|
||||||
// First (small) halfband 24 bit I/O
|
// First (small) halfband 24 bit I/O
|
||||||
small_hb_dec #(.WIDTH(WIDTH)) small_hb_i
|
small_hb_dec #(.WIDTH(WIDTH)) small_hb_i
|
||||||
(.clk(clk),.rst(rst),.bypass(~enable_hb1),.run(ddc_enb),
|
(.clk(clk),.rst(idle_rst),.bypass(~enable_hb1),.run(ddc_enb),
|
||||||
.stb_in(strobe_cic),.data_in(i_cic),.stb_out(strobe_hb1),.data_out(i_hb1));
|
.stb_in(strobe_cic),.data_in(i_cic),.stb_out(strobe_hb1),.data_out(i_hb1));
|
||||||
|
|
||||||
small_hb_dec #(.WIDTH(WIDTH)) small_hb_q
|
small_hb_dec #(.WIDTH(WIDTH)) small_hb_q
|
||||||
(.clk(clk),.rst(rst),.bypass(~enable_hb1),.run(ddc_enb),
|
(.clk(clk),.rst(idle_rst),.bypass(~enable_hb1),.run(ddc_enb),
|
||||||
.stb_in(strobe_cic),.data_in(q_cic),.stb_out(),.data_out(q_hb1));
|
.stb_in(strobe_cic),.data_in(q_cic),.stb_out(),.data_out(q_hb1));
|
||||||
|
|
||||||
// Second (large) halfband 24 bit I/O
|
// Second (large) halfband 24 bit I/O
|
||||||
wire [8:0] cpi_hb = enable_hb1 ? {cic_decim_rate,1'b0} : {1'b0,cic_decim_rate};
|
wire [8:0] cpi_hb = enable_hb1 ? {cic_decim_rate,1'b0} : {1'b0,cic_decim_rate};
|
||||||
hb_dec #(.WIDTH(WIDTH)) hb_i
|
hb_dec #(.WIDTH(WIDTH)) hb_i
|
||||||
(.clk(clk),.rst(rst),.bypass(~enable_hb2),.run(ddc_enb),.cpi(cpi_hb),
|
(.clk(clk),.rst(idle_rst),.bypass(~enable_hb2),.run(ddc_enb),.cpi(cpi_hb),
|
||||||
.stb_in(strobe_hb1),.data_in(i_hb1),.stb_out(strobe_hb2),.data_out(i_hb2));
|
.stb_in(strobe_hb1),.data_in(i_hb1),.stb_out(strobe_hb2),.data_out(i_hb2));
|
||||||
|
|
||||||
hb_dec #(.WIDTH(WIDTH)) hb_q
|
hb_dec #(.WIDTH(WIDTH)) hb_q
|
||||||
(.clk(clk),.rst(rst),.bypass(~enable_hb2),.run(ddc_enb),.cpi(cpi_hb),
|
(.clk(clk),.rst(idle_rst),.bypass(~enable_hb2),.run(ddc_enb),.cpi(cpi_hb),
|
||||||
.stb_in(strobe_hb1),.data_in(q_hb1),.stb_out(),.data_out(q_hb2));
|
.stb_in(strobe_hb1),.data_in(q_hb1),.stb_out(),.data_out(q_hb2));
|
||||||
|
|
||||||
//scalar operation (gain of 6 bits)
|
//scalar operation (gain of 6 bits)
|
||||||
|
|||||||
@@ -46,6 +46,10 @@ module duc_chain
|
|||||||
wire [3:0] tx_femux_a, tx_femux_b;
|
wire [3:0] tx_femux_a, tx_femux_b;
|
||||||
wire enable_hb1, enable_hb2;
|
wire enable_hb1, enable_hb2;
|
||||||
wire rate_change;
|
wire rate_change;
|
||||||
|
|
||||||
|
reg idle_rst;
|
||||||
|
always @(posedge clk)
|
||||||
|
idle_rst <= (rst | ~duc_enb);
|
||||||
|
|
||||||
setting_reg #(.my_addr(BASE+0)) sr_0
|
setting_reg #(.my_addr(BASE+0)) sr_0
|
||||||
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
|
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
|
||||||
@@ -66,13 +70,13 @@ module duc_chain
|
|||||||
reg strobe_hb2 = 1;
|
reg strobe_hb2 = 1;
|
||||||
|
|
||||||
cic_strober #(.WIDTH(8))
|
cic_strober #(.WIDTH(8))
|
||||||
cic_strober(.clock(clk),.reset(rst),.enable(duc_enb & ~rate_change),.rate(interp_rate),
|
cic_strober(.clock(clk),.reset(idle_rst),.enable(duc_enb & ~rate_change),.rate(interp_rate),
|
||||||
.strobe_fast(1),.strobe_slow(strobe_cic_pre) );
|
.strobe_fast(1),.strobe_slow(strobe_cic_pre) );
|
||||||
cic_strober #(.WIDTH(2))
|
cic_strober #(.WIDTH(2))
|
||||||
hb2_strober(.clock(clk),.reset(rst),.enable(duc_enb & ~rate_change),.rate(enable_hb2 ? 2 : 1),
|
hb2_strober(.clock(clk),.reset(idle_rst),.enable(duc_enb & ~rate_change),.rate(enable_hb2 ? 2 : 1),
|
||||||
.strobe_fast(strobe_cic_pre),.strobe_slow(strobe_hb2_pre) );
|
.strobe_fast(strobe_cic_pre),.strobe_slow(strobe_hb2_pre) );
|
||||||
cic_strober #(.WIDTH(2))
|
cic_strober #(.WIDTH(2))
|
||||||
hb1_strober(.clock(clk),.reset(rst),.enable(duc_enb & ~rate_change),.rate(enable_hb1 ? 2 : 1),
|
hb1_strober(.clock(clk),.reset(idle_rst),.enable(duc_enb & ~rate_change),.rate(enable_hb1 ? 2 : 1),
|
||||||
.strobe_fast(strobe_hb2_pre),.strobe_slow(strobe_hb1_pre) );
|
.strobe_fast(strobe_hb2_pre),.strobe_slow(strobe_hb1_pre) );
|
||||||
|
|
||||||
always @(posedge clk) strobe_hb1 <= strobe_hb1_pre;
|
always @(posedge clk) strobe_hb1 <= strobe_hb1_pre;
|
||||||
@@ -81,9 +85,7 @@ module duc_chain
|
|||||||
|
|
||||||
// NCO
|
// NCO
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
if(rst)
|
if(idle_rst)
|
||||||
phase <= 0;
|
|
||||||
else if(~duc_enb)
|
|
||||||
phase <= 0;
|
phase <= 0;
|
||||||
else
|
else
|
||||||
phase <= phase + phase_inc;
|
phase <= phase + phase_inc;
|
||||||
@@ -102,24 +104,24 @@ module duc_chain
|
|||||||
// but the default case inside hb_interp handles this
|
// but the default case inside hb_interp handles this
|
||||||
|
|
||||||
hb_interp #(.IWIDTH(18),.OWIDTH(18),.ACCWIDTH(WIDTH)) hb_interp_i
|
hb_interp #(.IWIDTH(18),.OWIDTH(18),.ACCWIDTH(WIDTH)) hb_interp_i
|
||||||
(.clk(clk),.rst(rst),.bypass(~enable_hb1),.cpo(cpo),.stb_in(strobe_hb1),.data_in({bb_i, 2'b0}),.stb_out(strobe_hb2),.data_out(hb1_i));
|
(.clk(clk),.rst(idle_rst),.bypass(~enable_hb1),.cpo(cpo),.stb_in(strobe_hb1),.data_in({bb_i, 2'b0}),.stb_out(strobe_hb2),.data_out(hb1_i));
|
||||||
hb_interp #(.IWIDTH(18),.OWIDTH(18),.ACCWIDTH(WIDTH)) hb_interp_q
|
hb_interp #(.IWIDTH(18),.OWIDTH(18),.ACCWIDTH(WIDTH)) hb_interp_q
|
||||||
(.clk(clk),.rst(rst),.bypass(~enable_hb1),.cpo(cpo),.stb_in(strobe_hb1),.data_in({bb_q, 2'b0}),.stb_out(strobe_hb2),.data_out(hb1_q));
|
(.clk(clk),.rst(idle_rst),.bypass(~enable_hb1),.cpo(cpo),.stb_in(strobe_hb1),.data_in({bb_q, 2'b0}),.stb_out(strobe_hb2),.data_out(hb1_q));
|
||||||
|
|
||||||
small_hb_int #(.WIDTH(18)) small_hb_interp_i
|
small_hb_int #(.WIDTH(18)) small_hb_interp_i
|
||||||
(.clk(clk),.rst(rst),.bypass(~enable_hb2),.stb_in(strobe_hb2),.data_in(hb1_i),
|
(.clk(clk),.rst(idle_rst),.bypass(~enable_hb2),.stb_in(strobe_hb2),.data_in(hb1_i),
|
||||||
.output_rate(interp_rate),.stb_out(strobe_cic),.data_out(hb2_i));
|
.output_rate(interp_rate),.stb_out(strobe_cic),.data_out(hb2_i));
|
||||||
small_hb_int #(.WIDTH(18)) small_hb_interp_q
|
small_hb_int #(.WIDTH(18)) small_hb_interp_q
|
||||||
(.clk(clk),.rst(rst),.bypass(~enable_hb2),.stb_in(strobe_hb2),.data_in(hb1_q),
|
(.clk(clk),.rst(idle_rst),.bypass(~enable_hb2),.stb_in(strobe_hb2),.data_in(hb1_q),
|
||||||
.output_rate(interp_rate),.stb_out(strobe_cic),.data_out(hb2_q));
|
.output_rate(interp_rate),.stb_out(strobe_cic),.data_out(hb2_q));
|
||||||
|
|
||||||
cic_interp #(.bw(18),.N(4),.log2_of_max_rate(7))
|
cic_interp #(.bw(18),.N(4),.log2_of_max_rate(7))
|
||||||
cic_interp_i(.clock(clk),.reset(rst),.enable(duc_enb & ~rate_change),.rate(interp_rate),
|
cic_interp_i(.clock(clk),.reset(idle_rst),.enable(duc_enb & ~rate_change),.rate(interp_rate),
|
||||||
.strobe_in(strobe_cic),.strobe_out(1),
|
.strobe_in(strobe_cic),.strobe_out(1),
|
||||||
.signal_in(hb2_i),.signal_out(i_interp));
|
.signal_in(hb2_i),.signal_out(i_interp));
|
||||||
|
|
||||||
cic_interp #(.bw(18),.N(4),.log2_of_max_rate(7))
|
cic_interp #(.bw(18),.N(4),.log2_of_max_rate(7))
|
||||||
cic_interp_q(.clock(clk),.reset(rst),.enable(duc_enb & ~rate_change),.rate(interp_rate),
|
cic_interp_q(.clock(clk),.reset(idle_rst),.enable(duc_enb & ~rate_change),.rate(interp_rate),
|
||||||
.strobe_in(strobe_cic),.strobe_out(1),
|
.strobe_in(strobe_cic),.strobe_out(1),
|
||||||
.signal_in(hb2_q),.signal_out(q_interp));
|
.signal_in(hb2_q),.signal_out(q_interp));
|
||||||
|
|
||||||
|
|||||||
@@ -2,5 +2,5 @@ TypesDB "/usr/share/collectd/umtrx.types.db"
|
|||||||
|
|
||||||
LoadPlugin exec
|
LoadPlugin exec
|
||||||
<Plugin exec>
|
<Plugin exec>
|
||||||
Exec "fairwaves:fairwaves" "/usr/share/umtrx/umtrx2collectd.py"
|
Exec "fairwaves-monitoring" "/usr/share/umtrx/umtrx2collectd.py"
|
||||||
</Plugin>
|
</Plugin>
|
||||||
|
|||||||
@@ -1,5 +1 @@
|
|||||||
Voltages1 PR1:GAUGE:0:32, PR2:GAUGE:0:32, PF1:GAUGE:0:32, PF2:GAUGE:0:32
|
sensor value:GAUGE:U:U
|
||||||
Voltages2 Zero:GAUGE:0:32, Vin:GAUGE:0:32, VinPA:GAUGE:0:32, DCOUT:GAUGE:0:32
|
|
||||||
Temperature A:GAUGE:-40:120, B:GAUGE:-40:120
|
|
||||||
ReturnLoss C1:GAUGE:0:32, C2:GAUGE:0:32
|
|
||||||
VSWR C1:GAUGE:0:32, C2:GAUGE:0:32
|
|
||||||
|
|||||||
@@ -2,74 +2,52 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sched,time
|
import sched, time
|
||||||
|
|
||||||
from umtrx_property_tree import umtrx_property_tree
|
from umtrx_property_tree import umtrx_property_tree
|
||||||
from umtrx_vswr import umtrx_vswr
|
from umtrx_vswr import umtrx_vswr
|
||||||
|
|
||||||
|
BOARD_ID = "0"
|
||||||
|
SENSORS_PATH = "/mboards/{id}/sensors".format(id=BOARD_ID)
|
||||||
|
VSWR_CALIBRATION = 0 # = TM10_VSWR_cal
|
||||||
|
|
||||||
HOSTNAME = os.environ['COLLECTD_HOSTNAME'] if 'COLLECTD_HOSTNAME' in os.environ else 'localhost'
|
HOSTNAME = os.environ['COLLECTD_HOSTNAME'] if 'COLLECTD_HOSTNAME' in os.environ else 'localhost'
|
||||||
INTERVAL = os.environ['COLLECTD_INTERVAL'] if 'COLLECTD_INTERVAL' in os.environ else '60'
|
INTERVAL = os.environ['COLLECTD_INTERVAL'] if 'COLLECTD_INTERVAL' in os.environ else '60'
|
||||||
|
|
||||||
|
|
||||||
umtrx = umtrx_property_tree()
|
umtrx = umtrx_property_tree()
|
||||||
umtrx.connect()
|
umtrx.connect()
|
||||||
|
|
||||||
sensors_path = "/mboards/0/sensors"
|
# typically this yields: ['tempA', 'tempB', 'voltagePR1', 'voltagePF1', 'voltagePR2', 'voltagePF2', 'voltagezero', 'voltageVin', 'voltageVinPA', 'voltageDCOUT']
|
||||||
res = umtrx.list_path_raw(sensors_path)
|
sensors_list = umtrx.list_path_raw(SENSORS_PATH).get("result", [])
|
||||||
# ['tempA', 'tempB', 'voltagePR1', 'voltagePF1', 'voltagePR2', 'voltagePF2', 'voltagezero', 'voltageVin', 'voltageVinPA', 'voltageDCOUT']
|
|
||||||
sensors_list = res.get('result', [])
|
|
||||||
|
|
||||||
|
|
||||||
# Voltages1 PR1:GAUGE:0:32, PR2:GAUGE:0:32, PF1:GAUGE:0:32, PF2:GAUGE:0:32
|
|
||||||
# Voltages2 Zero:GAUGE:0:32, Vin:GAUGE:0:32, VinPA:GAUGE:0:32, DCOUT:GAUGE:0:32
|
|
||||||
# Temperature A:GAUGE:-40:120, B:GAUGE:-40:120,
|
|
||||||
# ReturnLoss C1:GAUGE:0:32, C2:GAUGE:0:32
|
|
||||||
# VSWR C1:GAUGE:0:32, C2:GAUGE:0:32
|
|
||||||
|
|
||||||
def publish_set(name, values):
|
|
||||||
res = [HOSTNAME, name, INTERVAL]
|
|
||||||
res.extend(values)
|
|
||||||
src = "PUTVAL \"%s/UmTRX/%s\" interval=%s N:" + ":".join(["%s"] * len(values))
|
|
||||||
print src % tuple(res)
|
|
||||||
|
|
||||||
|
|
||||||
def publish():
|
def publish():
|
||||||
sets = {'Voltages1': ['VoltagePR1', 'VoltagePR2', 'VoltagePF1', 'VoltagePF2'],
|
now = time.time()
|
||||||
'Voltages2': ['Voltagezero', 'VoltageVin', 'VoltageVinPA', 'VoltageDCOUT'],
|
|
||||||
'Temperature': ['TempA', 'TempB'], 'VSWR': ['Channel_1_VSWR', 'Channel_2_VSWR'],
|
|
||||||
'ReturnLoss': ['Channel_1_ReturnLoss', 'Channel_2_ReturnLoss']}
|
|
||||||
|
|
||||||
current_sensors = {}
|
current_sensors = {sensor: umtrx.query_sensor_value(SENSORS_PATH + "/" + sensor) for sensor in sensors_list}
|
||||||
|
|
||||||
for sensor in sensors_list:
|
for channel in ["1", "2"]:
|
||||||
sensor_data = umtrx.query_sensor_raw(sensors_path + "/" + sensor)['result']
|
vpf_name = "voltagePF" + channel
|
||||||
current_sensors[sensor_data['name']] = sensor_data['value']
|
vpr_name = "voltagePR" + channel
|
||||||
|
|
||||||
# vswr_calibration = TM10_VSWR_cal
|
if vpf_name in current_sensors and vpr_name in current_sensors:
|
||||||
vswr_calibration = 0
|
vswr = umtrx_vswr(float(current_sensors[vpf_name]), float(current_sensors[vpr_name]), VSWR_CALIBRATION)
|
||||||
|
current_sensors["VSWR" + channel] = vswr.vswr()
|
||||||
|
current_sensors["ReturnLoss" + channel] = vswr.return_loss()
|
||||||
|
|
||||||
for num in [1, 2]:
|
for name, value in current_sensors.items():
|
||||||
vpr_name = 'voltagePR' + str(num)
|
print "PUTVAL {host}/umtrx-{id}/sensor-{name} interval={interval} {now}:{value}".format(
|
||||||
vpf_name = 'voltagePF' + str(num)
|
host=HOSTNAME, id=BOARD_ID, name=name, interval=INTERVAL, now=now, value=value)
|
||||||
if vpr_name in sensors_list and vpf_name in sensors_list:
|
|
||||||
vpr = float(umtrx.query_sensor_value(sensors_path + '/' + vpr_name))
|
|
||||||
vpf = float(umtrx.query_sensor_value(sensors_path + '/' + vpf_name))
|
|
||||||
|
|
||||||
vswr = umtrx_vswr(vpf, vpr, vswr_calibration)
|
|
||||||
|
|
||||||
current_sensors['Channel_%d_VSWR' % num] = vswr.vswr()
|
|
||||||
current_sensors['Channel_%d_ReturnLoss' % num] = vswr.return_loss()
|
|
||||||
|
|
||||||
for key, values in sets.iteritems():
|
|
||||||
publish_set(key, [current_sensors[name] for name in values])
|
|
||||||
|
|
||||||
|
|
||||||
s = sched.scheduler(time.time, time.sleep)
|
s = sched.scheduler(time.time, time.sleep)
|
||||||
|
|
||||||
|
|
||||||
def timer_loop():
|
def timer_loop():
|
||||||
s.enter(float(INTERVAL), 1, timer_loop, ())
|
s.enter(float(INTERVAL), 1, timer_loop, ())
|
||||||
publish()
|
publish()
|
||||||
|
|
||||||
|
|
||||||
timer_loop()
|
timer_loop()
|
||||||
s.run()
|
s.run()
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user